BZOJ 3110 [Zjoi2013]K大数查询

题解:整体二分

以时间为关键字进行整体二分

用线段树维护区间和

Woc这题居然爆int,以后注意爆int的可能

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200009;
const int inf=1000000000;
typedef long long Lint;

int n,m;
int ans[maxn];
int isquery[maxn];

struct SegmentTree{
	int l,r,tag,cle;
	Lint sum;
}tree[maxn<<1];
void pushup(int now){
	tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
}
void pushdown(int now){
	if(tree[now].cle){
		tree[now<<1].sum=tree[now<<1].tag=0;
		tree[now<<1|1].sum=tree[now<<1|1].tag=0;
		tree[now<<1].cle=tree[now<<1|1].cle=1;
		tree[now].cle=0;
	}
	if(tree[now].tag){
		tree[now<<1].tag+=tree[now].tag;
		tree[now<<1|1].tag+=tree[now].tag;
		tree[now<<1].sum+=1LL*tree[now].tag*(tree[now<<1].r-tree[now<<1].l+1);
		tree[now<<1|1].sum+=1LL*tree[now].tag*(tree[now<<1|1].r-tree[now<<1|1].l+1);
		tree[now].tag=0;
	}
}
void BuildTree(int now,int l,int r){
	tree[now].l=l;tree[now].r=r;
	tree[now].tag=tree[now].sum=tree[now].cle=0;
	if(l==r)return;
	int mid=(l+r)>>1;
	BuildTree(now<<1,l,mid);
	BuildTree(now<<1|1,mid+1,r);
}
void Updatasec(int now,int ll,int rr,int x){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		tree[now].tag+=x;
		tree[now].sum+=1LL*x*(tree[now].r-tree[now].l+1);
		return;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	if(ll<=mid)Updatasec(now<<1,ll,rr,x);
	if(rr>mid)Updatasec(now<<1|1,ll,rr,x);
	pushup(now);
}
Lint Querysum(int now,int ll,int rr){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		return tree[now].sum;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	Lint ret=0;
	if(ll<=mid)ret+=Querysum(now<<1,ll,rr);
	if(rr>mid)ret+=Querysum(now<<1|1,ll,rr);
	return ret;
}

struct OPTS{
	int opty,l,r,z,t;
}opt[maxn],q[maxn];
int cmpt(const OPTS &rhs1,const OPTS &rhs2){
	return rhs1.t<rhs2.t;
}

void ClearTree(){
	tree[1].cle=1;
	tree[1].sum=tree[1].tag=0;
}

void Div(int l,int r,int Lb,int Rb){
//	cout<<l<<' '<<r<<' '<<Lb<<' '<<Rb<<endl;
	if(l>r)return;
	if(Lb==Rb){
		for(int i=l;i<=r;++i){
			ans[opt[i].t]=Lb;
		}
		return;
	}
	int midans=(Lb+Rb)>>1;
	
	ClearTree();
	
	int t1=l,t2=r;
	for(int i=l;i<=r;++i){
		if(opt[i].opty==1){
			if(opt[i].z>midans){
				Updatasec(1,opt[i].l,opt[i].r,1);
				q[t2--]=opt[i];
			}else{
				q[t1++]=opt[i];
			}
		}else{
			Lint tmp=Querysum(1,opt[i].l,opt[i].r);
			if(tmp>=opt[i].z){
				q[t2--]=opt[i];
			}else{
				opt[i].z-=tmp;
				q[t1++]=opt[i];
			}
		}
	}
	for(int i=t1;i<=(r+t1)/2;++i){
		swap(q[i],q[r-i+t1]);
	}
	for(int i=l;i<=r;++i)opt[i]=q[i];
	Div(l,t1-1,Lb,midans);
	Div(t1,r,midans+1,Rb);
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i){
		scanf("%d%d%d%d",&opt[i].opty,&opt[i].l,&opt[i].r,&opt[i].z);
		opt[i].t=i;
		if(opt[i].opty==2)isquery[i]=1;
	}
	BuildTree(1,1,n);
	Div(1,m,-n,n);
	
	for(int i=1;i<=m;++i){
		if(isquery[i])printf("%d\n",ans[i]);
	}
	return 0;
}

  

posted @ 2018-02-20 12:31  ws_zzy  阅读(159)  评论(0编辑  收藏  举报