第二分块求条
  • 板块灌水区
  • 楼主Eterna
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/12/26 13:35
  • 上次更新2024/12/26 18:09:14
查看原帖
第二分块求条
1348260
Eterna楼主2024/12/26 13:35

rt

#include<bits/stdc++.h>
#define bl[i] ((i-1)/block+1)
#define rd read()
#define gc getchar()
using namespace std;
const int S=1005,M=500005,N=1000005,V=100005;
inline int read()
{
	int x=0,s=gc;
	while(!isdigit(s))s=gc;
	while(isdigit(s))x=(x<<1)+(x<<3)+(s^48),s=gc;
	return x;
}
struct ques{int op,l,r,x;}qr[M];
int n,q,val[N],lazy,mx;
int a[N],block,tot;
int L[S],R[S],ans[M];
int siz[V],fa[N],nam[V];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline int merge(int x,int y)
{
	if(nam[y])fa[nam[x]]=nam[y];
	else val[nam[y]=nam[x]]=y;
	siz[y]+=siz[x];
	nam[x]=siz[x]=0;
}
void build(int x)
{
	lazy=0,mx=INT_MIN;
	for(int i=L[x];i<=R[x];i++)
	{
		mx=max(mx,a[i]),++siz[a[i]];
		if(!nam[a[i]])val[i]=a[i],nam[a[i]]=i,fa[i]=i;
		else fa[i]=nam[a[i]];
	}
}
inline void alchange(int x)
{
	if(x*2>mx-lazy)
	{
		for(int i=x+lazy+1;i<=mx;i++)if(nam[i])merge(i,i-x);
		mx=min(mx,x+lazy);
		return;
	}
	for(int i=x+lazy;i>=lazy;i--)if(nam[i])merge(i,i+x);
	lazy+=x;
}
inline void change(int id,int l,int r,int x)
{
	l=max(l,L[id]),r=min(r,R[id]);
	for(int i=L[id],w;i<=R[id];i++)
	{
		w=val[find(i)];
		a[i]=w-lazy;
		siz[w]=nam[w]=0;
	}
	for(int i=L[id];i<=R[id];i++)val[i]=0;
	for(int i=l;i<=r;i++)if(a[i]>x)a[i]-=x;
	build(id);
}
inline int ask(int id,int l,int r,int x)
{
	int ans=0;
	l=max(l,L[id]),r=min(r,R[id]);
	for(int i=l;i<=r;i++)if(val[find(i)]-lazy==x)++ans;
	return ans;
}
void solve()
{
	for(int i=1;i<=tot;i++)
	{
		memset(siz,0,sizeof(siz));
		memset(fa,0,sizeof(fa));
		build(i);
		for(int j=1;j<=q;j++)
		{
			if(L[i]>qr[j].r||R[i]<qr[j].l)continue;
			if(qr[j].op==1)
			{
				if(qr[j].l<=L[i]&&qr[j].r>=R[i])alchange(qr[j].x);
				else change(i,qr[j].l,qr[j].r,qr[j].x);
			}
			else
			{
				if(qr[j].x+lazy<=100001)
				{
					if(qr[j].l<=L[i]&&qr[j].r>=R[i])ans[j]+=siz[qr[j].x+lazy];
					else ans[j]+=ask(i,qr[j].l,qr[j].r,qr[j].x);
				}
			}
		}
	}
}
signed main()
{
	n=rd,q=rd;block=sqrt(n),tot=n/block+(n%block?1:0);
	for(int i=1;i<=n;i++)a[i]=rd;
	for(int i=1;i<=q;i++)qr[i]={rd,rd,rd,rd};
	for(int i=1;i<=tot;i++)L[i]=R[i-1]+1,R[i]=i*block;
	R[tot]=n,solve();
	for(int i=1;i<=q;i++)if(qr[i].op==2)cout<<ans[i]<<'\n';
	return 0;
}
2024/12/26 13:35
加载中...