萌新刚学逐块处理,23pts求调
查看原帖
萌新刚学逐块处理,23pts求调
999274
CNS_5t0_0r2楼主2024/7/26 15:46
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 1,SqrtN = 1e3 + 1,M = 5e5 + 1,V = 1e5 + 10;
int n,m,a[N],max_a;
int op,l,r,x;
struct block{
	int l,r,Max,tag;
} b[SqrtN];
int belong[N];
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(int id){
	b[id].Max = 0;
	for(int i = b[id].l;i <= b[id].r;i++){
		b[id].Max = max(b[id].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(int id){
	for(int i = b[id].l;i <= b[id].r;i++){
		a[i] = DSU[father(i)].v;
		val[a[i]].root = val[a[i]].cnt = 0;
		a[i] -= b[id].tag;
	}
	b[id].tag = 0;
	for(int i = b[id].l;i <= b[id].r;i++)
		DSU[i].fa = 0;
}
inline void build_block(){
	block_cnt = block_len = (int)sqrt(n);
	for(int i = 1;i <= block_cnt;i++){
		b[i].l = b[i - 1].r + 1;
		b[i].r = b[i].l + block_len - 1;
	}
	b[block_cnt].r = n;
	for(int i = 1;i <= block_cnt;i++)
		for(int j = b[i].l;j <= b[i].r;j++)
			belong[j] = i;
}
inline void make_tag(int id,int v){
	if(v <= b[id].Max - b[id].tag - v){
		for(int i = b[id].tag + 1;i <= b[id].tag + v;i++)
			if(val[i].root)
				merge(i,i + v);
		b[id].tag += v;
	}
	else{
		for(int i = b[id].Max;i > b[id].tag + v;i--)
			if(val[i].root)
				merge(i,i - v);
		b[id].Max = min(b[id].Max,b[id].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;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		max_a = max(max_a,a[i]);
	}
	build_block();
	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++){
	    if(i != 1){
	        for(int j = 1;j < V;j++){
		        val[j].root = val[j].cnt = 0;
		    }
	    }
		push_up(i);
		
		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 > b[i].r || r < b[i].l)//块与操作区间无交 
				continue;
			if(l <= b[i].l && b[i].r <= r){//块完全包含在当前操作区间重 
				if(op == 1)
					make_tag(i,x);
				else
					if(x + b[i].tag <= max_a)
						ans[j] += val[x + b[i].tag].cnt;
			}
			else{//否则就是散块 
				l = max(l,b[i].l);
				r = min(r,b[i].r);
				if(op == 1){
					for(int k = l;k <= r;k++)
						if(a[k] > x)
							a[k] -= x;
					push_up(i);
				}
				else{
					for(int k = l;k <= r;k++)
						if(DSU[father(k)].v - b[i].tag == x)
							ans[j]++;
				}
			}
		}
	}
	for(int i = 1;i <= m;i++)
		if(q[i].op == 2)
			cout << ans[i] << '\n';
	return 0;
} 
2024/7/26 15:46
加载中...