逐块处理 56pts WA求调
查看原帖
逐块处理 56pts WA求调
999274
CNS_5t0_0r2楼主2024/8/7 10:52
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 1,M = 5e5 + 1,V = 1e5 + 10;
int n,m,a[N],max_a;
int op,l,r,x;
int block_l,block_r,Max,tag;
int block_cnt,block_len;
struct node{
	int root,cnt;
} val[V];
struct DSU_node{
	int fa,v;
} DSU[N];
inline int father(int x){
	return x == DSU[x].fa ? x : DSU[x].fa = father(DSU[x].fa);
}
inline void merge(int a,int b){
	node &u = val[a],&v = val[b];
	if(v.root)
		DSU[u.root].fa = v.root;
	else{
		v.root = u.root;
		DSU[u.root].v = b;
	}
	v.cnt += u.cnt;
	u.root = u.cnt = 0;
}
inline void push_up(){
	Max = 0;
	for(int i = block_l;i <= block_r;i++){
		Max = max(Max,a[i]);
		val[a[i]].cnt++;
		if(val[a[i]].root)
			DSU[i].fa = val[a[i]].root;
		else{
			DSU[i].v = a[i];
			val[a[i]].root = DSU[i].fa = i;
		}
	}
}
inline void push_down(){
	for(int i = block_l;i <= block_r;i++){
		a[i] = DSU[father(i)].v;
		val[a[i]].root = val[a[i]].cnt = 0;
		a[i] -= tag;
	}
	tag = 0;
	for(int i = block_l;i <= block_r;i++)
		DSU[i].fa = 0;
}
inline void make_tag(int v){
	if(v <= Max - tag - v){
		for(int i = tag + 1;i <= tag + v;i++)
			if(val[i].root)
				merge(i,i + v);
		tag += v;
	}
	else{
		for(int i = Max;i > tag + v;i--)
			if(val[i].root)
				merge(i,i - v);
		Max = min(Max,tag + v);
	}
}
struct OPTION{
	int op,l,r,x;
} q[M];
int ans[M];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	block_len = block_cnt = sqrt(n);
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		max_a = max(max_a,a[i]);
	}
	for(int i = 1;i <= m;i++)
		cin >> q[i].op >> q[i].l >> q[i].r >> q[i].x;
	//逐块处理
	
	for(int i = 1;i <= block_cnt;i++){
		block_l = block_r + 1;
		block_r = block_l + block_len - 1;
		if(i == block_cnt)
			block_r = n;
	    for(int j = 1;j <= max_a;j++)
		    val[j].root = val[j].cnt = 0;
		push_up();
		
		for(int j = 1;j <= m;j++){
			int op = q[j].op,l = q[j].l,r = q[j].r,x = q[j].x;
			if(l > block_r || r < block_l)//块与操作区间无交 
				continue;
			if(l <= block_l && block_r <= r){//块完全包含在当前操作区间中 
				if(op == 1)
					make_tag(x);
				else
					if(x + tag <= max_a)
						ans[j] += val[x + tag].cnt;
			}
			else{//否则就是散块 
				l = max(l,block_l);
				r = min(r,block_r);
				if(op == 1){
					push_down();
					for(int k = l;k <= r;k++)
						if(a[k] > x)
							a[k] -= x;
					push_up();
				}
				else{
					for(int k = l;k <= r;k++)
						if(DSU[father(k)].v - tag == x)
							ans[j]++;
				}
			}
		}
	}
	for(int i = 1;i <= m;i++)
		if(q[i].op == 2)
			cout << ans[i] << '\n';
	return 0;
} 
2024/8/7 10:52
加载中...