BZOJ 2653 middle 题解
题意:一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给一个序列,并进行一些询问。每次询问起点在[a,b],终点在[c,d]的序列的中位数。
题解:首先有一个思路:对于一个序列S,假设它的中位数是m,则S中>=m的元素个数一定>=n
那么对于一个序列S和一个数m,我们将>=m的元素设置为1,其余为-1,得到一个新数列S‘。则$\sum S'$ >=0
对于每个询问我们二分一下m即可。如果在区间[a,d]内有一段包含[b,c]的连续子序列的和>=0,则答案>=当前二分的值。
求最大子序列的和相信大家都会做。。用线段树维护lmax,rmax,sum值即可
但是如果每次都暴力构建线段树的话太慢了。。和暴力差不了多少
于是我们可以用可持久化线段树做。。
然后这题就解决了。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #define fr first 4 #define sc second 5 const int MAXN=20000+5; 6 const int INF=~0U>>1; 7 struct Info{ 8 int sum,maxl,maxr; 9 Info(int v) {sum=maxl=maxr=v;} 10 Info() {} 11 }; 12 Info operator+(const Info& a,const Info& b) 13 { 14 Info ans; 15 ans.sum=a.sum+b.sum; 16 ans.maxl=std::max(a.maxl,a.sum+std::max(0,b.maxl)); 17 ans.maxr=std::max(b.maxr,b.sum+std::max(0,a.maxr)); 18 return ans; 19 } 20 struct Tree{ 21 int l,r; 22 Info v; 23 Tree* pl,*pr; 24 Tree(int l,int r,int all):l(l),r(r) 25 { 26 if(l+1==r) 27 { 28 v=Info(all); 29 return; 30 } 31 int m=(l+r)>>1; 32 pl=new Tree(l,m,all); 33 pr=new Tree(m,r,all); 34 v=pl->v+pr->v; 35 } 36 Tree(int l,int r,Tree* pl,Tree* pr):l(l),r(r),pl(pl),pr(pr) {v=pl->v+pr->v;} 37 Info query(int L,int R) 38 { 39 if(L<=l && R>=r) return v; 40 int m=(l+r)>>1; 41 if(R<=m) return pl->query(L,R); 42 else if(L>=m) return pr->query(L,R); 43 else return pl->query(L,R)+pr->query(L,R); 44 } 45 Tree* change(int pos,int w) 46 { 47 if(l+1==r) return new Tree(l,r,w); 48 int m=(l+r)>>1; 49 if(pos<m) return new Tree(l,r,pl->change(pos,w),pr); 50 else return new Tree(l,r,pl,pr->change(pos,w)); 51 } 52 }; 53 typedef std::pair<int,int> P; 54 P ps[MAXN]; 55 Tree* root[MAXN]; 56 int n; 57 inline bool judge(int v,int a,int b,int c,int d) //[a,b) [c,d) 58 { 59 Tree* r=root[v]; 60 return (r->query(a,b).maxr+(b<c?r->query(b,c).sum:0)+r->query(c,d).maxl)>=0; 61 } 62 int main() 63 { 64 scanf("%d",&n); 65 for(int i=0;i<n;++i) 66 { 67 int t; 68 scanf("%d",&t); 69 ps[i]=P(t,i); 70 } 71 std::sort(ps,ps+n); 72 root[0]=new Tree(0,n,1); 73 for(int i=1;i<n;++i) 74 root[i]=root[i-1]->change(ps[i-1].sc,-1); 75 int q,last=0; 76 scanf("%d",&q); 77 while(q--) 78 { 79 int t[4]; 80 for(int i=0;i<4;++i) scanf("%d",t+i),t[i]=(t[i]+last)%n; 81 std::sort(t,t+4); 82 int l=0,r=n; 83 while(l+1<r) 84 { 85 int m=(l+r)>>1; 86 if(judge(m,t[0],t[1]+1,t[2],t[3]+1)) l=m; 87 else r=m; 88 } 89 printf("%d\n",ps[l].fr); 90 last=ps[l].fr; 91 } 92 return 0; 93 }