POJ2104 K-th number (整体二分)
作者:互联网
刚学了整体二分,用这种解法来解决这道题。
首先对于每个询问时可以二分解决的,这也是可以使用整体二分的前提。将原来的序列看成是插入操作,和询问操作和在一起根据值域进行二分。用树状数组来检验二分值。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010,INF=1e9; 4 struct node{ 5 int op,x,y,z; 6 }q[N<<1],lq[N<<1],rq[N<<1]; 7 int n,m,t,c[N],ans[N]; 8 9 int lowbit(int x){ 10 return x&(-x); 11 } 12 13 int ask(int x){ 14 int sum=0; 15 while(x){ 16 sum+=c[x]; 17 x-=lowbit(x); 18 } 19 return sum; 20 } 21 22 void change(int x,int y){ 23 while(x<=n){ 24 c[x]+=y; 25 x+=lowbit(x); 26 } 27 } 28 29 void solve(int L,int R,int l,int r){ 30 if(l>r) return ;//操作序列为空 31 if(L==R){ 32 for(int i=l;i<=r;i++){ 33 if(q[i].op>0) ans[q[i].op]=L; 34 } 35 return ; 36 } 37 int mid=(L+R)>>1; 38 int lt=0,rt=0; 39 for(int i=l;i<=r;i++){ 40 if(q[i].op==0){ 41 if(q[i].y<=mid) change(q[i].x,1),lq[++lt]=q[i]; 42 else rq[++rt]=q[i]; 43 } 44 else{ 45 int cnt=ask(q[i].y)-ask(q[i].x-1); 46 if(cnt>=q[i].z) lq[++lt]=q[i]; 47 else q[i].z-=cnt,rq[++rt]=q[i]; 48 } 49 } 50 for(int i=r;i>=l;i--){ 51 if(q[i].op==0 && q[i].y<=mid) change(q[i].x,-1); 52 } 53 for(int i=1;i<=lt;i++) q[l+i-1]=lq[i]; 54 for(int i=1;i<=rt;i++) q[l+lt+i-1]=rq[i]; 55 solve(L,mid,l,l+lt-1); 56 solve(mid+1,R,l+lt,r); 57 } 58 59 int main(){ 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=n;i++){ 62 int val;scanf("%d",&val); 63 q[++t].op=0,q[t].x=i,q[t].y=val; 64 } 65 for(int i=1;i<=m;i++){ 66 int l,r,k; 67 scanf("%d%d%d",&l,&r,&k); 68 q[++t].op=i,q[t].x=l,q[t].y=r,q[t].z=k; 69 } 70 solve(-INF,INF,1,t); 71 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 72 return 0; 73 }
标签:二分,rt,return,int,number,lt,th,POJ2104,op 来源: https://www.cnblogs.com/yhxnoerror/p/16483472.html