\(\mathcal{Description}\)

  Link.

  给定序列 \(\{a_n\}\),处理 \(m\) 次操作:

  1. 给定 \(l,r,x\),把 \([l,r]\) 内所有 \(>x\) 的数减去 \(x\);
  2. 给定 \(l,r,x\),查询 \([l,r]\) 内 \(x\) 的出现次数。

  \(n\le10^6\),\(m\le5\times10^5\),\(0\le a_i,x\le10^5\)。

\(\mathcal{Solution}\)

  巧妙的分块题。

  分块,设块长为 \(B\),对于每一块,利用值域 \(V\) 不大,直接使用桶的方式维护信息。把桶看做一条线段 \([v_l,v_r]\),每次修改相当于把线段的后端截下一段平移到前端,可用启发式合并 + 并查集确保复杂度。最终复杂度为 \(\mathcal O(qB+\frac{nV}{B}+\frac{qn}{B})\),大概取 \(B=1.5\times10^3\) 就好。注意卡空间,对每个块离线处理。

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) inline char fgc() {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && ( q = buf + fread( p = buf, 1, 1 << 17, stdin ), p == q )
? EOF : *p++;
} inline int rint() {
int x = 0, s = fgc();
for ( ; s < '0' || '9' < s; s = fgc() );
for ( ; '0' <= s && s <= '9'; s = fgc() ) x = x * 10 + ( s ^ '0' );
return x;
} inline void wint( const int x ) {
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} inline int imin( const int u, const int v ) { return u < v ? u : v; }
inline int imax( const int u, const int v ) { return u < v ? v : u; } const int MAXN = 1e6, MAXM = 6e5, MAXV = 1e5, MAXS = 1500;
int n, m, a[MAXN + 5], ans[MAXM + 5];
struct Event { int op, l, r, x; } evt[MAXM + 5];
int fa[MAXN + 5], siz[MAXV + 5], rt[MAXV + 5], ref[MAXN + 5]; inline int find( const int x ) {
return x == fa[x] ? x : fa[x] = find( fa[x] );
} inline void unite( int x, int y ) {
assert( rt[x] );
if ( rt[y] ) fa[rt[x]] = rt[y];
else ref[rt[y] = rt[x]] = y;
siz[y] += siz[x], siz[x] = rt[x] = 0;
} inline void solve( const int bl, const int br ) {
int vl = 0, vr = 0; rep ( i, bl, br ) vr = a[i] < vr ? vr : a[i];
memset( rt, 0, sizeof rt ), memset( siz, 0, sizeof siz );
rep ( i, bl, br ) {
if ( rt[a[i]] ) fa[i] = rt[a[i]];
else rt[a[i]] = fa[i] = i, ref[i] = a[i];
++siz[a[i]];
} rep ( i, 1, m ) {
int x = evt[i].x, l = evt[i].l, r = evt[i].r;
if ( r < bl || l > br ) continue;
if ( evt[i].op == 1 ) { // modify.
if ( vr - vl <= x ) continue;
if ( l <= bl && br <= r ) { // whole block update.
if ( x << 1 > vr - vl ) { // right to left.
per ( j, vr, vl + x + 1 ) if ( rt[j] ) unite( j, j - x );
vr = vl + x;
} else { // left to right.
rep ( j, vl + 1, vl + x ) if ( rt[j] ) unite( j, j + x );
vl += x;
}
} else { // partly update. curA = find(orgA)-vl.
rep ( j, bl, br ) {
a[j] = ref[find( j )];
siz[a[j]] = rt[a[j]] = 0;
a[j] -= vl;
} vl = vr = 0;
rep ( j, bl, br ) {
l <= j && j <= r && a[j] > x && ( a[j] -= x );
vr = vr < a[j] ? a[j] : vr;
if ( rt[a[j]] ) fa[j] = rt[a[j]];
else rt[a[j]] = fa[j] = j, ref[j] = a[j];
++siz[a[j]];
}
}
} else if ( vl + x <= vr ) { // meaningful query.
if ( l <= bl && br <= r ) { // whole block query.
ans[i] += siz[x + vl];
} else { // partly query.
rep ( j, imax( l, bl ), imin( r, br ) ) {
ans[i] += ref[find( j )] - vl == x;
}
}
}
}
} int main() {
n = rint(), m = rint();
rep ( i, 1, n ) a[i] = rint();
rep ( i, 1, m ) {
evt[i].op = rint();
evt[i].l = rint(), evt[i].r = rint(), evt[i].x = rint();
} for ( int l = 1, r; l <= n; l = r + 1 ) {
r = l + MAXS - 1; if ( r > n ) r = n;
solve( l, r );
} rep ( i, 1, m ) if ( evt[i].op == 2 ) {
wint( ans[i] ), putchar( '\n' );
}
return 0;
}

最新文章

  1. Windows 8.1 新增控件之 CommandBar
  2. python学习道路(day1note)(变量,注释,用户输入,格式化输出,if,while,for循环并扩展练习)
  3. 【接口测试】Jenkins+Ant+Jmeter搭建持续集成的接口测试平台
  4. 使用dbms_logmnr查看日志文件
  5. hdu 2058
  6. XtraGrid的若干种用法 z
  7. 事务的使用示例及WinForm实现中的若干问题
  8. 【Android基础】短信的发送
  9. python之实现缓存环
  10. [CSS3] 学习笔记-CSS3常用操作
  11. 集成python双版本详解
  12. 八大排序算法---基于python
  13. HttpClient发送Post请求,get请求
  14. PHP 使用redis实现秒杀
  15. 一次linux问题分析原因的简要记录
  16. Java字节码里的invoke操作&amp;&amp;编译时的静态绑定与动态绑定
  17. Kubernetes之Controllers三
  18. Qt5学习记录:QString与int值互相转换
  19. python---map 用法 [转载]
  20. endnote插入参考文献后的对齐方式和缩进空格

热门文章

  1. Linux命令查看各端口号占用情况
  2. Launch agent by connecting it to the master
  3. ssh到localhost或127.0.0.1拒绝连接
  4. Echart可视化学习(十一)
  5. Kube-OVN1.5.0新版本发布,支持鲲鹏云平台网络平面部署
  6. 【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)
  7. java(基于springboot项目或maven项目均可) 操作mongodb
  8. leetcode 921. 使括号有效的最少添加
  9. Go 转义字符及风格
  10. 带你十天轻松搞定 Go 微服务系列(三)