bzoj 3110 K大数查询 Posted on 2019-06-23 | Edited on 2019-06-25 | Views: 整体二分. 整体二分. 因为修改操作对二分答案的贡献是给一段区间 $+1$ ,所以用线段树来维护即可. 一次分治结束后并不能直接重置线段树,因为这样每次操作就和整个序列长度线性相关了. 将修改操作 $+1$ 的部分都 $-1$ 撤回即可. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149#include<bits/stdc++.h>using namespace std;typedef long long ll;inline ll read(){ ll out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=5e4+10;int n,m,ans[MAXN],qcnt=0;struct Node{ int a,b; ll c; int type,id;}q[MAXN<<2],ql[MAXN],qr[MAXN];struct Segtree{ struct node { ll sum,tag; node(){sum=0;tag=0;} }Tree[MAXN<<2];#define root Tree[o]#define lson Tree[o<<1]#define rson Tree[o<<1|1] void pushup(int o) { root.sum=lson.sum+rson.sum; } void modifiy(int o,int c,int l,int r) { root.sum+=1LL*c*(r-l+1); root.tag+=c; } void pushdown(int o,int l,int r) { if(root.tag) { int mid=(l+r)>>1; modifiy(o<<1,root.tag,l,mid); modifiy(o<<1|1,root.tag,mid+1,r); root.tag=0; } } void upd(int o,int l,int r,int L,int R,int c) { if(l>R || L>r) return; if(L<=l && r<=R) { modifiy(o,c,l,r); return; } pushdown(o,l,r); int mid=(l+r)>>1; if(L<=mid) upd(o<<1,l,mid,L,R,c); if(R>mid) upd(o<<1|1,mid+1,r,L,R,c); pushup(o); } ll query(int o,int l,int r,int L,int R) { if(l>R || L>r) return 0; if(L<=l && r<=R) return root.sum; ll res=0; pushdown(o,l,r); int mid=(l+r)>>1; if(L<=mid) res+=query(o<<1,l,mid,L,R); if(R>mid) res+=query(o<<1|1,mid+1,r,L,R); return res; }}T;void solve(int l,int r,int L,int R){ if(l>r || L>R) return; if(l==r) { for(int i=L;i<=R;++i) if(q[i].type==2) ans[q[i].id]=l; return; } int cntl=0,cntr=0; int mid=(l+r)>>1; for(int i=L;i<=R;++i) { if(q[i].type==1) { if(q[i].c>mid) { T.upd(1,1,n,q[i].a,q[i].b,1); qr[++cntr]=q[i]; } else ql[++cntl]=q[i]; } else { ll tmp=T.query(1,1,n,q[i].a,q[i].b); if(tmp>=q[i].c) qr[++cntr]=q[i]; else if(tmp<q[i].c) { q[i].c-=tmp; ql[++cntl]=q[i]; } } } for(int i=L;i<=R;++i) if(q[i].type==1 && q[i].c>mid) T.upd(1,1,n,q[i].a,q[i].b,-1); for(int i=1;i<=cntl;++i) q[L+i-1]=ql[i]; for(int i=1;i<=cntr;++i) q[L+i+cntl-1]=qr[i]; solve(l,mid,L,L+cntl-1); solve(mid+1,r,L+cntl,R);}int main(){ n=read(),m=read(); for(int i=1;i<=m;++i) { q[i].type=read(); q[i].a=read(); q[i].b=read(); q[i].c=read(); if(q[i].type==2) q[i].id=++qcnt; } solve(-n,n,1,m); for(int i=1;i<=qcnt;++i) printf("%d\n",ans[i]); return 0;}