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; }