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值即可

但是如果每次都暴力构建线段树的话太慢了。。和暴力差不了多少

于是我们可以用可持久化线段树做。。

然后这题就解决了。。

 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 }
View Code

 

posted @ 2015-04-15 17:59  lowsfish  阅读(188)  评论(0编辑  收藏  举报