[BZOJ2653]middle 主席树+二分

2653: middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2042  Solved: 1123
[Submit][Status][Discuss]

Description

一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。给你一个
长度为n的序列s。回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。位置也从0开始标号。我会使用一些方式强制你在线。

 

Input

第一行序列长度n。接下来n行按顺序给出a中的数。
接下来一行Q。然后Q行每行a,b,c,d,我们令上个询问的答案是
x(如果这是第一个询问则x=0)。
令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
将q从小到大排序之后,令真正的
要询问的a=q[0],b=q[1],c=q[2],d=q[3]。  
输入保证满足条件。
第一行所谓“排过序”指的是从大到小排序!
 

 

Output

Q行依次给出询问的答案。

 

Sample Input

5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0

271451044
271451044
969056313

Sample Output

 

HINT

 

  0:n,Q<=100

1,...,5:n<=2000

0,...,19:n<=20000,Q<=25000


 

 

Source

 

我们二分中位数,对于大于mid的数赋值为1,小于mid的数为-1。若最大的区间和大于0则可行。

考虑建一颗主席树(维护权值线段树),root[i]为中位数为i时的前缀树。

二分查询即可。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxn 20005
 8 #define ls(i) t[i].s[0]
 9 #define rs(i) t[i].s[1]
10 using namespace std;
11 int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 struct tmp {
18     int v,id;
19     bool operator <(const tmp tt) const {return v<tt.v;}
20 }a[maxn];
21 struct data {
22     int lm,rm,sum,s[2];
23 }t[maxn*20];
24 int n,q,sz;
25 int root[maxn];
26 void pushup(int x) {
27     t[x].lm=max(t[ls(x)].lm,t[ls(x)].sum+t[rs(x)].lm);
28     t[x].rm=max(t[rs(x)].rm,t[rs(x)].sum+t[ls(x)].rm);
29     t[x].sum=t[rs(x)].sum+t[ls(x)].sum;
30 }
31 void build(int &rt,int l,int r) {
32     rt=++sz;
33     if(l==r) {t[rt].sum=t[rt].lm=t[rt].rm=1;return;}
34     int mid=l+r>>1;
35     build(ls(rt),l,mid);build(rs(rt),mid+1,r);
36     pushup(rt);
37     
38 }
39 void update(int p,int &rt,int l,int r,int x) {
40     rt=++sz;
41     t[rt]=t[p];
42     if(l==r) {t[rt].sum=-1;t[rt].lm=t[rt].rm=0;return;}
43     int mid=l+r>>1;
44     if(x<=mid) update(ls(p),ls(rt),l,mid,x);
45     else update(rs(p),rs(rt),mid+1,r,x);
46     pushup(rt);
47 }
48 int qs(int rt,int l,int r,int x,int y) {
49     if(x>y) return 0;
50     if(l>=x&&r<=y) return t[rt].sum;
51     int mid=l+r>>1,ans=0;
52     if(x<=mid) ans+=qs(ls(rt),l,mid,x,y);
53     if(y>mid) ans+=qs(rs(rt),mid+1,r,x,y);
54     return ans;
55 }
56 int ql(int rt,int l,int r,int x,int y) {
57     if(x>y) return 0;
58     if(l>=x&&r<=y) return t[rt].lm;
59     int mid=l+r>>1,ans=0;
60     if(x<=mid) ans=max(ql(ls(rt),l,mid,x,y),ans);
61     if(y>mid) ans=max(qs(ls(rt),l,mid,x,mid)+ql(rs(rt),mid+1,r,x,y),ans);
62     return ans;
63 }
64 int qr(int rt,int l,int r,int x,int y) {
65     if(x>y) return 0;
66     if(l>=x&&r<=y) return t[rt].rm;
67     int mid=l+r>>1,ans=0;
68     if(x<=mid) ans=max(qs(rs(rt),mid+1,r,mid+1,y)+qr(ls(rt),l,mid,x,y),ans);
69     if(y>mid) ans=max(qr(rs(rt),mid+1,r,x,y),ans);
70     return ans;
71 }
72 bool check(int x,int q1,int q2,int q3,int q4) {
73     int s=qs(root[x],0,n-1,q2,q3)+ql(root[x],0,n-1,q3+1,q4)+qr(root[x],0,n-1,q1,q2-1);
74     return s>=0;
75 }
76 int main() {
77     t[0].sum=t[0].lm=t[0].rm=0;
78     n=read();
79     for(int i=0;i<n;i++) a[i].v=read(),a[i].id=i;
80     sort(a,a+n);
81     build(root[0],0,n-1);
82     for(int i=1;i<n;i++) update(root[i-1],root[i],0,n-1,a[i-1].id);
83     int ans=0;
84     q=read();
85     for(int i=1;i<=q;i++) {
86         int ask[5];
87         for(int j=1;j<=4;j++) ask[j]=(read()+ans)%n;
88         sort(ask+1,ask+5);
89         int L=0,R=n-1;
90         while(L<=R) {
91             int mid=L+R>>1;
92             if(check(mid,ask[1],ask[2],ask[3],ask[4])) L=mid+1;
93             else R=mid-1;
94         }
95         ans=a[L-1].v;
96         printf("%d\n",ans);
97     }
98 }
View Code

 

posted @ 2018-01-02 21:32  wls001  阅读(127)  评论(0编辑  收藏  举报