整体二分代码
查看原帖
整体二分代码
365021
masterhuang楼主2022/5/29 12:35

发现就一个将整体二分的题解,而且我按那个方法写写挂了。于是发个自己的方法。
rk(x)定义成区间<=x的数。
x的排名就是rk(x-1)+1。 x的前驱变成区间排名为rk(x-1)的数。
x的后继变成区间排名为rk(x)+1的数。
然后两次整体二分分别求一下就可以了,但是细节很麻烦。 代码给大家提供一个参考,有思路不明白的可以问我。

#include<bits/stdc++.h>
#define LL long long
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
#define pb push_back
using namespace std;
const int N=5e4+5,inf=2147483647;
struct node{int x,y,k,op,id;}a[N*3],_a[N],__a[N*3];
int n,m,old[N],tot,tot1,tot2,tot3,tot4,ans[N],b[N],to[N*3],e[N],oo[N*3],aans[N];
inline int lb(int x){return x&-x;}
inline void add(int wz,int num){for(;wz<=n;b[wz]+=num,wz+=lb(wz));}
inline int ask(int wz){int ans=0;for(;wz>=1;ans+=b[wz],wz-=lb(wz));return ans;}
void slove(int l,int r,vector<int>qu)
{
	if(!qu.size()) return;
	if(l==r)
	{
		for(int i:qu) if(a[i].op==2) ans[a[i].id]=l-1;
		return;
	}
	int mid=(l+r)>>1;
	vector<int>q1,q2;
	for(int i:qu)
	{
		if(a[i].op==1)
		{
			int t=ask(a[i].y)-ask(a[i].x-1);
			if(mid>a[i].k) q1.pb(i);
			else
			{
				if(a[i].k==-inf) aans[a[i].id]+=t;
				else ans[a[i].id]+=t;
				q2.pb(i);
			}
		}
		if(a[i].op==2)
		{
			int t=ask(a[i].y)-ask(a[i].x-1);
			if(a[i].k<=t) q1.pb(i);
			else a[i].k-=t,q2.pb(i);
		}
		if(a[i].op==3)
		{
			if(a[i].y<=mid) add(a[i].x,a[i].k),q1.pb(i);
			else q2.pb(i);
		}
	}
	for(int i:qu) if(a[i].op==3&&a[i].y<=mid) add(a[i].x,-a[i].k);
	slove(l,mid,q1);slove(mid+1,r,q2);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&old[i]),old[i]++,a[++tot]={i,old[i],1,3,0};
	for(int i=1,opt,l,r,x;i<=m;i++)
	{
		scanf("%d",&opt);
		if(opt==1) scanf("%d%d%d",&l,&r,&x),a[++tot]={l,r,x,1,++tot1},ans[tot1]=1,oo[tot1]=opt;
		if(opt==2) scanf("%d%d%d",&l,&r,&x),a[++tot]={l,r,x,2,++tot1},oo[tot1]=opt;
		if(opt==3) scanf("%d%d",&l,&x),x++,a[++tot]={l,old[l],-1,3,0},a[++tot]={l,old[l]=x,1,3,0};
		if(opt==4) scanf("%d%d%d",&l,&r,&x),a[++tot]={l,r,x,1,++tot1},oo[tot1]=opt,_a[++tot2]={l,r,tot1,4,tot},to[tot]=tot2,a[++tot]={l,r,-inf,1,++tot4};
		if(opt==5) scanf("%d%d%d",&l,&r,&x),x++,a[++tot]={l,r,x,1,++tot1},oo[tot1]=opt,_a[++tot2]={l,r,tot1,5,tot},to[tot]=tot2;
	}
	vector<int>qu;
	for(int i=1;i<=tot;i++) qu.push_back(i),__a[i]=a[i];
	slove(1,1e8+2,qu);
	for(int i=1;i<=tot;i++)
	{
		if(__a[i].op==3) a[++tot3]=__a[i];
		if(a[i+1].k==-inf){if(ans[a[i].id]==aans[a[i].id]){ans[a[i].id]=-inf;continue;}}
		if(to[i])
		{
			node x=_a[to[i]];
			a[++tot3].k=ans[x.k];if(x.op==5) a[tot3].k++;
			a[tot3].op=2;a[tot3].x=x.x;a[tot3].y=x.y;a[tot3].id=x.k;
			a[tot3+1]=a[tot3];
		}
	}
	qu.clear();for(int i=1;i<=(tot=tot3);i++) qu.push_back(i);
	slove(1,1e8+2,qu);
	for(int i=1;i<=tot1;i++) if(oo[i]==5&&ans[i]>1e8) ans[i]=inf;
	for(int i=1;i<=tot1;i++) printf("%d\n",ans[i]);
	return 0;
}
2022/5/29 12:35
加载中...