【BZOJ】【P3110】【Zjoi2013】【K大数查询】【题解】【整体二分】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3110

整体二分真是太神了

改成线段树就可以支持区间修改了

想当年痛苦的写树套树然后T成翔

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cctype>
using namespace std;
const int maxn=50005;
int n,m;
struct seg{
	struct node{
		int sum,lazy;
		node(){sum=lazy=0;}
	}t[maxn<<2];
	#define lson i<<1,l,mid
	#define rson i<<1|1,mid+1,r
	#define L i<<1
	#define R i<<1|1
	void rz(int i){
		t[i].sum=t[L].sum+t[R].sum;
	}
	void pushdown(int i,int l,int r){
		if(t[i].lazy){
			int mid=(l+r)>>1;
			t[L].lazy+=t[i].lazy;
			t[L].sum+=(mid-l+1)*t[i].lazy;			
			t[R].lazy+=t[i].lazy;
			t[R].sum+=(r-mid)*t[i].lazy;			
			t[i].lazy=0;
		}
	}
	void Add(int i,int l,int r,int l0,int r0,int d){
		if(l0<=l&&r0>=r){
			t[i].lazy+=d;
			t[i].sum+=(r-l+1)*d;
			return;
		}int mid=(l+r)>>1;
		pushdown(i,l,r);
		if(l0<=mid)Add(lson,l0,r0,d);
		if(r0>mid)Add(rson,l0,r0,d);rz(i);
	}
	int Qsum(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r)return t[i].sum;
		pushdown(i,l,r);
		int mid=(l+r)>>1,ans=0;
		if(l0<=mid)ans+=Qsum(lson,l0,r0);
		if(r0>mid)ans+=Qsum(rson,l0,r0);
		return ans;
	}
	void Add(int l,int r,int d){
		Add(1,1,n,l,r,d);
	}
	int Qsum(int l,int r){
		return Qsum(1,1,n,l,r);
	}
	#undef lson
	#undef rson
	#undef L
	#undef R
}T,T2;
int getint(){
	int res=0,f=1;char c=getchar();
	while(!isdigit(c))f=f==-1||c=='-'?-1:1,c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res*f;
}
struct qes{
	int x,y,z,ty,ind,cur,delta;
	qes(int _x=0,int _y=0,int _z=0,int _ty=0,int _ind=0,int _cur=0,int _delta=0):
		x(_x),y(_y),z(_z),ty(_ty),ind(_ind),cur(_cur),delta(_delta){}
}q[maxn];
int anss[maxn],mx,md;
bool part(qes &Q){
	if(Q.ty==2){
		if(Q.cur+Q.delta>Q.z-1)return 1;
		Q.cur+=Q.delta;Q.delta=0;return 0;
	}return Q.z<=md;
}
void solve(int lef,int rig,int l,int r){
	if(lef>rig)return;
	if(l==r){
		for(int i=lef;i<=rig;i++)if(q[i].ty==2)
		anss[q[i].ind]=l;
		return;
	}int mid=(l+r)>>1;md=mid;
	for(int i=lef;i<=rig;i++){
		if(q[i].ty==1&&q[i].z<=mid)T.Add(q[i].x,q[i].y,1);
		if(q[i].ty==2)q[i].delta=T.Qsum(q[i].x,q[i].y);
	}for(int i=lef;i<=rig;i++)
	if(q[i].ty==1&&q[i].z<=mid)T.Add(q[i].x,q[i].y,-1);
	int dv=stable_partition(q+lef,q+rig+1,part)-q-1;
	solve(lef,dv,l,mid);
	solve(dv+1,rig,mid+1,r);
}
int main(){
	n=getint();m=getint();
	for(int i=1;i<=m;i++){
		int op=getint(),l=getint(),r=getint(),c=getint();
		if(op==1)
			q[i]=qes(l,r,c,op),mx=max(mx,c),T2.Add(l,r,1);
		else q[i]=qes(l,r,T2.Qsum(l,r)-c+1,op,++anss[0]);			
	}
	solve(1,m,0,mx);
	for(int i=1;i<=anss[0];i++)printf("%d\n",anss[i]);
	return 0;
}



你可能感兴趣的:(bzoj)