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

 

posted @ 2018-08-02 11:16  bztMinamoto  阅读(254)  评论(0编辑  收藏  举报
Live2D