分块+并查集 WA+TLE 30 pts 求条
查看原帖
分块+并查集 WA+TLE 30 pts 求条
936183
_zSqr_Mahiro_Oyama_楼主2024/10/23 21:32
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5,M=5e5+5,V=1e5+10;
struct Q{
	int op,l,r,x;
}q[M];

int n,m,a[N],ans[M];
int len,L[N],R[N];
int bl,br,Max,tag; //当前块的l,r 最大 减标记 
int prt[N],rt[V],val[N],cnt[V];
//并查集 rt[i] 值i对应的根 val[i] 并查集中集合的根表示的数值 cnt[i] 值i的数量 

inline int Find(int x){
	if(x==prt[x])return x;
	return prt[x]=Find(prt[x]);
}
inline void Merge(int x,int y){//此处合并是将值x合并到值y 
	if(rt[y]){
		prt[rt[x]]=rt[y];
	}else{
		rt[y]=rt[x];
		val[rt[y]]=y;
	}
	cnt[y]+=cnt[x];
	rt[x]=0;
	cnt[x]=0;
}

inline void build(){
	memset(rt,0,sizeof(rt));
	memset(cnt,0,sizeof(cnt));
	Max=tag=0;
	for(register int i=bl;i<=br;++i){
		val[i]=0;
		Max=max(Max,a[i]); 
		if(!rt[a[i]]){
			rt[a[i]]=i;
			val[i]=a[i];
			prt[i]=i;
		}else{
			prt[i]=rt[a[i]];
		}
		cnt[a[i]]++;
	}
}
inline void update(int x){//整块修改 
	if(Max-tag<(x<<1)){//2x>Max,把所有>x的数减x 
		for(register int i=x+tag+1;i<=Max;++i)
			if(rt[i])Merge(i,i-x);
		if(tag+x<Max)Max=tag+x;
	}else{//2x<=Max,把所有<=x的数加x并打减法标记 
		for(register int i=tag+x;i>=tag;--i)
			if(rt[i])Merge(i,i+x);
		tag+=x;
	}
}
inline void rebuild(int l,int r,int x){//部分块重构 
	for(register int i=bl;i<=br;++i){
		a[i]=val[Find(i)];
		rt[a[i]]=0;
		cnt[a[i]]=0;
		a[i]-=tag;
	}
	int ql=max(bl,l),qr=min(br,r);
	for(register int i=ql;i<=qr;++i)
		if(a[i]>x)a[i]-=x;
	Max=tag=0;
	for(register int i=bl;i<=br;++i){
		val[i]=0;
		Max=max(Max,a[i]);
		if(!rt[a[i]]){
			rt[a[i]]=i;
			val[i]=a[i];
			prt[i]=i;
		}else{
			prt[i]=rt[a[i]];
		}
		cnt[a[i]]++;
	}
}
inline int query(int l,int r,int x){
	if(x+tag>100001)return 0;
	if(l<=bl&&br<=r)
		return cnt[x+tag];
	int ql=max(bl,l),qr=min(br,r),res=0;
	for(register int i=ql;i<=qr;++i)
		res+=(val[Find(i)]+tag==x);
	return res;
}

template<typename T>
inline void read(T &x){
    char c;
    x=0;
    int fu=1;
    c=getchar();
    while(c>'9'||c<'0'){
        if(c=='-')fu=-1;
        c=getchar();
    }
    while(c<='9'&&c>='0'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=fu;
}
template<typename T>
inline void print(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)print(x/10);
    putchar(x%10+'0');
}

int main(){
	read(n);read(m);
	len=n/sqrt(n);
	for(register int i=1;i<=n;++i)
		read(a[i]);
	for(register int i=1;i<=m;++i){
		read(q[i].op);read(q[i].l);read(q[i].r);read(q[i].x);
	}
	for(register int i=1,block=sqrt(n);i<=len;++i){
		L[i]=(i-1)*block+1;
		R[i]=i*block;
	}
	if(R[len]<n){
		len++;
		L[len]=R[len-1]+1;
		R[len]=n;
	}
	for(register int i=1;i<=len;++i){
		bl=L[i];br=R[i];
		build();
		for(register int j=1;j<=m;++j){
			if(q[j].op==1){
				if(q[j].l<=bl&&br<=q[j].r)
					update(q[j].x);
				else
					rebuild(q[j].l,q[j].r,q[j].x);
			}else{
				ans[j]+=query(q[j].l,q[j].r,q[j].x);
			}
		}
	}
	for(register int i=1;i<=m;++i)
		if(q[i].op==2){print(ans[i]);printf("\n");}
	return 0;
}
2024/10/23 21:32
加载中...