【bzoj2653】【middle】【主席树+二分答案】
Description
一个长度为 n 的序列 a ,设其排过序之后为 b ,其中位数定义为 b[n/2] ,其中 a,b 从 0 开始标号 , 除法取下整。
给你一个长度为 n 的序列 s 。回答 Q 个这样的询问 : s 的左端点在 [a,b] 之间 , 右端点在 [c,d] 之间的子序列中 ,最大的中位数。
其中 a
Solution
对着题解理解了半天……又对着代码调了半天……最后发现竟然是一个函数名没写orz
不过不得不说这题真的是主席树好题
先考虑二分答案,找出区间内比mid小的数有多少
因为对答案的贡献只有有或没有,所以可以把比mid小的都设为-1,比mid大的都设为1,如果区间内的和大于等于0,说明mid可行,继续二分下去
然而如果离散之后对每一个值建树,空间毫无疑问爆炸
于是只要用主席树维护一下就可以了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 inline int read(){ 9 #define num ch-'0' 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch=='-')&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 char obuf[1<<24],*o=obuf; 19 inline void print(int x){ 20 if(x>9) print(x/10); 21 *o++=x%10+48; 22 } 23 const int N=20005,M=N*30; 24 int n,Pre,q,cnt; 25 int rt[N],p[5]; 26 struct node{ 27 int l,r,lmx,rmx,sum; 28 }t[M],op; 29 struct data{ 30 int x,id; 31 inline bool operator <(const data &b)const 32 {return x<b.x;} 33 }a[N]; 34 inline void pushup(int x){ 35 t[x].sum=t[t[x].l].sum+t[t[x].r].sum; 36 t[x].lmx=max(t[t[x].l].lmx,t[t[x].l].sum+t[t[x].r].lmx); 37 t[x].rmx=max(t[t[x].r].rmx,t[t[x].r].sum+t[t[x].l].rmx); 38 } 39 void build(int &now,int l,int r){ 40 now=++cnt; 41 if(l==r){t[now].lmx=t[now].rmx=t[now].sum=1;return;} 42 int mid=(l+r)>>1; 43 build(t[now].l,l,mid); 44 build(t[now].r,mid+1,r); 45 pushup(now); 46 } 47 void update(int last,int &now,int l,int r,int k){ 48 now=++cnt; 49 if(l==r){t[now].lmx=t[now].rmx=t[now].sum=-1;return;} 50 int mid=(l+r)>>1; 51 if(k<=mid) t[now].r=t[last].r,update(t[last].l,t[now].l,l,mid,k); 52 else t[now].l=t[last].l,update(t[last].r,t[now].r,mid+1,r,k); 53 pushup(now); 54 } 55 node merge(node x,node y){ 56 node z; 57 z.sum=x.sum+y.sum; 58 z.lmx=max(x.lmx,x.sum+y.lmx); 59 z.rmx=max(y.rmx,y.sum+x.rmx); 60 return z; 61 } 62 node find(int x,int l,int r,int y,int z){ 63 if(y>z) return op; 64 if(l==y&&r==z) return t[x]; 65 int mid=(l+r)>>1; 66 if(z<=mid) return find(t[x].l,l,mid,y,z); 67 else if(y>mid) return find(t[x].r,mid+1,r,y,z); 68 else return merge(find(t[x].l,l,mid,y,mid),find(t[x].r,mid+1,r,mid+1,z)); 69 } 70 int query(int x){ 71 return find(rt[x],1,n,p[1],p[2]).rmx+find(rt[x],1,n,p[2]+1,p[3]-1).sum+find(rt[x],1,n,p[3],p[4]).lmx; 72 } 73 int main(){ 74 //freopen("testdata.in","r",stdin); 75 n=read(); 76 for(int i=1;i<=n;++i) a[i].x=read(),a[i].id=i; 77 sort(a+1,a+1+n); 78 build(rt[1],1,n); 79 for(int i=2;i<=n;++i) update(rt[i-1],rt[i],1,n,a[i-1].id); 80 q=read(); 81 while(q--){ 82 int x=read(),y=read(),z=read(),k=read(); 83 p[1]=(x+Pre)%n+1,p[2]=(y+Pre)%n+1,p[3]=(z+Pre)%n+1,p[4]=(k+Pre)%n+1; 84 sort(p+1,p+5); 85 int l=1,r=n,ans=1; 86 while(l<=r){ 87 int mid=(l+r)>>1; 88 int f=query(mid); 89 if(f>=0) ans=mid,l=mid+1; 90 else r=mid-1; 91 } 92 Pre=a[ans].x; 93 print(a[ans].x),*o++='\n'; 94 } 95 fwrite(obuf,o-obuf,1,stdout); 96 return 0; 97 }
深深地明白自己的弱小