【Ynoi2018】五彩斑斓的世界

【Ynoi2018】五彩斑斓的世界

by AmanoKumiko

Description

给出一个长度为\(n\)的序列\(a\)\(m\)次操作

每次操作形如

\(1,l,r,x\) 给区间中大于\(x\)的数减去\(x\)

\(2,l,r,x\) 询问区间中\(x\)的出现次数

Input

第一行两个数\(n,m\)

第二行\(n\)个数读入序列

然后\(m\)行读入操作

Output

每组询问输出一个数表示答案

Sample Input

5 6
1 5 5 5 8
2 2 5 5
1 2 4 3
2 2 5 2
2 2 5 5
1 3 5 1
2 1 5 1

Sample Output

3
3
0
3

Data Constraint

\(1\le n\le 10^6,1\le m \le 5*10^5,0\le a,x\le 10^5\)

Solution

我们先思考两个朴素的做法

令最大值为\(m\)

1.暴力扫\([x+1,m]\)中的数,减去\(x\)

\(x=1\)时显然复杂度是错的

2.暴力扫\([1,x]\)中的数,加上\(x\),然后区间减去\(x\)

\(x=10^5\)时复杂度是错的

仔细分析,我们的值是单调不降的,

那么只要我们每次都能用一定的时间换取极差减少相应的值,

每个块的复杂度就达到了\(O(10^5)\)

换句话说,我们要平衡上面的两种做法

可以发现

\(m-x\le x\)时,第一种做法复杂度\(O(m-x)\),极差减少了\(O(m-x)\)

\(m-x>x\)时,第二种做法复杂度\(O(x)\),极差减少了\(O(x)\)

那么用并查集(第一分块)维护下出现次数就行了

这里还有个问题,空间只有\(64MB\)

我们采取一个nb的\(trick\):逐块处理,这样就解决啦

Code

#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 1000010
#define M 500010

namespace IO{
	const int sz=1<<22;
	char a[sz+5],b[sz+5],*p1=a,*p2=a,*t=b,p[105];
	inline char gc(){
		return p1==p2?(p2=(p1=a)+fread(a,1,sz,stdin),p1==p2?EOF:*p1++):*p1++;
	}
	template<class T>void read(T&x){
		x=0;char c=gc();
		for(;c<'0'||c>'9';c=gc());
		for(;c>='0'&&c<='9';c=gc())x=x*10+(c-'0');
	}
	inline void flush(){fwrite(b,1,t-b,stdout),t=b;}
	inline void pc(char x){*t++=x;if(t-b==sz)flush();}
	template<class T>void write(T x,char c='\n'){
		if(x==0)pc('0');int t=0;
		for(;x;x/=10)p[++t]=x%10+'0';
		for(;t;--t)pc(p[t]);pc(c);
	}
	struct F{~F(){flush();}}f;
}
using IO::read;
using IO::write;

int n,m,a[N],val[N],ans[N],be[N],L[N],R[N],wh[N],fa[N],cnt[N],Mx,tag;
struct node{int op,l,r,x;}q[M];

inline int get(int x){return fa[x]==x?x:(fa[x]=get(fa[x]));}

inline void rebuild(int x){
	Mx=tag=0;
	fd(i,R[x],L[x])wh[a[i]]=i,cnt[a[i]]=0,val[i]=0;
	fo(i,L[x],R[x]){
		Mx=max(Mx,a[i]);
		cnt[a[i]]++;
		fa[i]=wh[a[i]];
		if(fa[i]==i)val[i]=a[i];
	}
}

inline void clear(int x){
	fo(i,L[x],R[x])wh[val[get(i)]]=cnt[val[get(i)]]=0,a[i]=val[get(i)]-tag;
	fo(i,L[x],R[x])wh[a[i]]=cnt[a[i]]=0;
}

inline void line(int x,int y){
	if(wh[y]){
		cnt[y]+=cnt[x];
		cnt[x]=0;
		fa[wh[x]]=wh[y];
		wh[x]=0;
	}else{
		cnt[y]=cnt[x];
		cnt[x]=0;
		val[wh[y]=wh[x]]=y;
		wh[x]=0;
	}
}

int main(){
	read(n);read(m);
	fo(i,1,n)read(a[i]);
	fo(i,1,m)read(q[i].op),read(q[i].l),read(q[i].r),read(q[i].x);
	int sz=1300,cs=n/sz+1;
	fo(i,1,cs){
		L[i]=R[i-1]+1;R[i]=min(L[i]+sz-1,n);
		fo(j,L[i],R[i])be[j]=i;
	}
	fo(i,1,cs){
		rebuild(i);
		fo(j,1,m){
			int le=q[j].l,ri=q[j].r;
			le=max(le,L[i]);ri=min(ri,R[i]);
			if(le<=ri){
				if(q[j].op==1){
					if(Mx-tag<=q[j].x)continue;
					if(le==L[i]&&ri==R[i]){
						if(Mx-tag<=q[j].x*2){
							fo(k,q[j].x+tag+1,Mx)if(wh[k])line(k,k-q[j].x);
							Mx=min(Mx,q[j].x+tag);
						}else{
							fo(k,tag+1,tag+q[j].x)if(wh[k])line(k,k+q[j].x);
							tag+=q[j].x;
						}
					}else{
						fo(k,L[i],R[i])wh[val[get(k)]]=cnt[val[get(k)]]=0,a[k]=val[get(k)]-tag;
						fo(k,le,ri)if(a[k]>q[j].x)a[k]-=q[j].x;
						rebuild(i);
					}
				}else{
					if(le==L[i]&&ri==R[i]){
						if(wh[q[j].x+tag])ans[j]+=cnt[q[j].x+tag];
					}else{
						fo(k,le,ri)if(val[get(k)]==q[j].x+tag)ans[j]++;
					}
				}
			}
		}
		clear(i);
	}
	fo(i,1,m)if(q[i].op==2)write(ans[i]);
	return 0;
}
posted @ 2022-03-17 11:12  冰雾  阅读(51)  评论(0编辑  收藏  举报