2653: middle
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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
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 ",ans); 97 } 98 }