bzoj3110[Zjoi2013]K大数查询

刚刚学习了整体二分,练习一下。

太长时间没写线段树了,结果在这道题里,线段树没有写update函数,怎么调都调不出来,无奈只好翻别人程序,改了一下就过了。

还有一个非常麻烦的事情是边界问题,程序里有一些需要打小于,有一些打小于等于,解决这个问题一种方法是对程序逻辑良好的整体把握,另一种方法是大力对拍,把可能情况测一遍就行了。

样例太水,不要相信样例。

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL  long long
#define FILE "dealing"
#define up(i,j,n) for(int i=j;i<=n;i++)
LL read(){
	LL x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
const LL maxn=800000,mod=1000000007,inf=10000000000000LL;
bool cmin(LL& a,LL b){return a>b?a=b,true:false;}
bool cmax(LL& a,LL b){return a<b?a=b,true:false;}
LL n,m;
struct node{LL x,y,op,ans,k,id;}a[maxn],q1[maxn],q2[maxn];
bool cmp(node a,node b){return a.id<b.id;}
LL key,left,right;
LL delet[maxn],s[maxn],siz[maxn],flag[maxn];
void add(LL x,LL del){delet[x]+=del,s[x]+=siz[x]*del;}
void qing(LL x){delet[x]=s[x]=0;flag[x]=1;}
void updata(LL x){s[x]=s[x<<1]+s[x<<1|1];}
void pushdown(LL x){
	if(flag[x])qing(x<<1),qing(x<<1|1),flag[x]=0;
	if(delet[x])add(x<<1,delet[x]),add(x<<1|1,delet[x]),delet[x]=0;
}
void change(LL l,LL r,LL o){
	if(l>right||r<left)return;
	if(l>=left&&r<=right){add(o,key);return;}
	LL mid=(l+r)>>1;
	pushdown(o);
	change(l,mid,o<<1);
	change(mid+1,r,o<<1|1);
	updata(o);
}
void Change(LL L,LL R,LL d){
	left=L,right=R,key=d;
	change(1,n,1);
}
LL query(LL l,LL r,LL o){
	if(r<left||l>right)return 0;
	if(l>=left&&r<=right)return s[o];
	LL mid=(l+r)>>1;
	pushdown(o);
	return query(l,mid,o<<1)+query(mid+1,r,o<<1|1);
}
LL Query(LL L,LL R){
	left=L,right=R;
	return query(1,n,1);
}
void build(LL l,LL r,LL o){
	if(l==r){siz[o]=1;return;}
	LL mid=(l+r)>>1;
	build(l,mid,o<<1);
	build(mid+1,r,o<<1|1);
	siz[o]=siz[o<<1]+siz[o<<1|1];
}
LL sum[maxn];
void divide(LL L,LL R,LL l,LL r){
	if(l>r)return;
	if(L==R){
		up(i,l,r)if(a[i].op==2)a[i].ans=L;
		return;
	}
	qing(1);
	LL mid=(L+R)>>1;
	up(i,l,r){
		if(a[i].op==1&&a[i].k>mid)Change(a[i].x,a[i].y,1);
		else if(a[i].op==2)sum[i]=Query(a[i].x,a[i].y);
	}
	LL top1=0,top2=0;
	up(i,l,r){
		if(a[i].op==2){
			if(sum[i]<=a[i].k){
				a[i].k-=sum[i];
				q1[++top1]=a[i];
			}else q2[++top2]=a[i];
		}
		else {
			if(a[i].k>mid)q2[++top2]=a[i];
			else q1[++top1]=a[i];
		}
	}
	up(i,l,l+top1-1)a[i]=q1[i-l+1];
	up(i,l+top1,r)a[i]=q2[i-top1-l+1];
	divide(L,mid,l,l+top1-1);
	divide(mid+1,R,l+top1,r);
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read(),m=read();LL Min=inf,Max=-inf;
	up(i,1,m){
		a[i].op=read(),a[i].x=read(),a[i].y=read(),a[i].k=read();a[i].id=i;
		if(a[i].op==2)a[i].k-=1;
		if(a[i].op==1)cmin(Min,a[i].k),cmax(Max,a[i].k);
	}
	build(1,n,1);
	divide(Min,Max,1,m);
	sort(a+1,a+m+1,cmp);
	up(i,1,m)if(a[i].op==2)printf("%lld\n",a[i].ans);
	return 0;
}

  

posted @ 2017-02-24 16:43  CHADLZX  阅读(130)  评论(0编辑  收藏  举报