Mn Zn 求助卡常
查看原帖
Mn Zn 求助卡常
305891
Eraine楼主2023/6/17 17:25

rt,#8死活过不去

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=1e6;
const int M=5e5;
const int C=1e5;
const int K=800;
int num[2*C+5],fa[N+5],sz[N+5];
inline int Find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=Find(fa[x]);
}
inline void merge(int x,int y){
	if(x!=y){
		fa[x]=y;
		sz[y]+=sz[x];
	}
}
struct Query{
	int type;
	int l,r,x;
	int ansid;
}q[M+5];
int n,m,a[N+5],pos[N+5],L[K+5],R[K+5],maxn,tag;
inline void init(int p){
	memset(num,0,sizeof num);
	memset(sz,0,sizeof sz);
	maxn=tag=0;
	for(int i=L[p];i<=R[p];i++){
		fa[i]=i;sz[i]=1;
		if(!num[a[i]]){
			num[a[i]]=i;
		}else{
			merge(i,num[a[i]]);
		}
		maxn=max(maxn,a[i]);
	}
}
inline void update(int p,int qid){
	int l=q[qid].l,r=q[qid].r,x=q[qid].x;
	if(l<=L[p]&&r>=R[p]){
		if(maxn>x+x){
			for(int i=tag+x;i>=tag;i--){
				if(!num[i]){
					continue;
				}
				if(!num[i+x]){
					swap(num[i],num[i+x]);
					a[num[i+x]]=i+x;
				}else{
					merge(num[i],num[i+x]);
					num[i]=0;
				}
			}
			tag+=x;maxn-=x;
		}else{
			for(int i=tag+x+1;i<=tag+maxn;i++){
				if(!num[i]){
					continue;
				}
				if(!num[i-x]){
					swap(num[i],num[i-x]);
					a[num[i-x]]=i-x;
				}else{
					merge(num[i],num[i-x]);
					num[i]=0;
				}
			}
			maxn=min(maxn,x);
		}
	}else if(!(r<L[p]||l>R[p])){
		for(int i=L[p];i<=R[p];i++){
			a[i]=a[Find(i)];
		}
		for(int i=L[p];i<=R[p];i++){
			if(a[i]-tag<=x){
				continue;
			}
			num[a[i]]=0;
			sz[i]=0;
		}
		for(int i=L[p];i<=R[p];i++){
			if(a[i]-tag<=x){
				continue;
			}
			if(i>=l&&i<=r){
				a[i]-=x;
			}
			fa[i]=i;sz[i]=1;
			if(!num[a[i]]){
				num[a[i]]=i;
			}else{
				merge(i,num[a[i]]);
			}
		}
		maxn=0;
		for(int i=L[p];i<=R[p];i++){
			maxn=max(maxn,a[i]-tag);
		}
	}else{
		return;
	}
	while(!num[tag+maxn]||!sz[num[tag+maxn]]){
		maxn--;
	}
}
inline int query(int p,int qid){
	int l=q[qid].l,r=q[qid].r,x=q[qid].x,res=0;
	if(l<=L[p]&&r>=R[p]){
		return (num[tag+x]>0)?sz[num[tag+x]]:0;
	}else if(!(r<L[p]||l>R[p])){
		for(int i=L[p];i<=R[p];i++){
			a[i]=a[Find(i)];
			if(a[i]-tag==x&&i>=l&&i<=r){
				res++;
			}
		}
		return res;
	}
	return 0;
}
inline int read(){
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	int x=0;
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x;
}
inline void write(int x){
	if(!x){
		return;
	}
	write(x/10);
	putchar(x%10+'0');
}
int ans[M+5];
int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	int block=max(1250,int(sqrt(n*1.0)));
	int num=n/block+(n%block>0);
	for(int i=1;i<=num;i++){
		L[i]=R[i-1]+1;
		R[i]=R[i-1]+block;
	}
	R[num]=n;
	int ansSum=0;
	for(int i=1;i<=m;i++){
		q[i].type=read();q[i].l=read();q[i].r=read();q[i].x=read();
		if(q[i].type==2){
			q[i].ansid=++ansSum;
		}
	}
	for(int i=1;i<=num;i++){
		init(i);
		for(int j=1;j<=m;j++){
			if(q[j].type==1){
				update(i,j);
			}else{
				ans[q[j].ansid]+=query(i,j);
			}
		}
	}
	for(int i=1;i<=ansSum;i++){
		if(!ans[i]){
			putchar('0');
		}else{
			write(ans[i]);
		}
		putchar('\n');
	}
	return 0;
}
2023/6/17 17:25
加载中...