bzoj2653 -- 二分+主席树

Posted gjghfd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2653 -- 二分+主席树相关的知识,希望对你有一定的参考价值。

对于每一个询问二分答案。

设当前答案为x,将>=x的数的权值设为1,<x的数的权值设为-1。

当 [b+1,c-1]的权值和+[a,b]权值和最大的后缀+[c,d]权值和最大的前缀>=0时x可行。

先对每个数离散,然后以每个值建立主席树记录区间和、最大前缀、最大后缀就可以了。

时间复杂度:O(n*log3n)

 

代码:

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 #define N 20010
 8 struct Node{
 9     int l,r,s,lx,rx;
10 }c[N*80];
11 struct Ls{
12     int w,f;
13 }b[N];
14 vector<int>g[N];
15 int Num,i,j,k,l,r,Mid,n,m,Rt[N],Q,a[N],w[N],q[5],Ans;
16 inline int Max(int x,int y){return x<y?y:x;}
17 inline bool Cmp(Ls a,Ls b){return a.w<b.w;}
18 inline void Up(int x){
19     c[x].rx=Max(c[c[x].r].rx,c[c[x].l].rx+c[c[x].r].s);
20     c[x].lx=Max(c[c[x].l].lx,c[c[x].r].lx+c[c[x].l].s);
21     c[x].s=c[c[x].l].s+c[c[x].r].s;
22 }
23 inline void Build(int& x,int l,int r){
24     if(x==0)x=++Num;
25     if(l==r){
26         c[x].lx=c[x].rx=c[x].s=1;
27         return;
28     }
29     int Mid=l+r>>1;
30     Build(c[x].l,l,Mid);
31     Build(c[x].r,Mid+1,r);
32     Up(x);
33 }
34 inline void Update(int& x,int y,int l,int r,int z){
35     x=++Num;
36     c[x]=c[y];
37     if(l==r){
38         c[x].lx=c[x].rx=0;
39         c[x].s=-1;
40         return;
41     }
42     int Mid=l+r>>1;
43     if(z<=Mid)Update(c[x].l,c[y].l,l,Mid,z);else Update(c[x].r,c[y].r,Mid+1,r,z);
44     Up(x);
45 }
46 inline int Query_sum(int x,int l,int r,int L,int R){
47     if(l>=L&&r<=R)return c[x].s;
48     int Mid=l+r>>1;
49     int Ans=0;
50     if(Mid>=L)Ans+=Query_sum(c[x].l,l,Mid,L,R);
51     if(Mid<R)Ans+=Query_sum(c[x].r,Mid+1,r,L,R);
52     return Ans;
53 }
54 inline int Query_rx(int x,int l,int r,int L,int R){
55     if(l>=L&&r<=R)return c[x].rx;
56     int Mid=l+r>>1;
57     if(Mid>=R)return Query_rx(c[x].l,l,Mid,L,R);
58     if(Mid<L)return Query_rx(c[x].r,Mid+1,r,L,R);
59     return Max(Query_rx(c[x].r,Mid+1,r,L,R),Query_sum(c[x].r,Mid+1,r,L,R)+Query_rx(c[x].l,l,Mid,L,R));
60 }
61 inline int Query_lx(int x,int l,int r,int L,int R){
62     if(l>=L&&r<=R)return c[x].lx;
63     int Mid=l+r>>1;
64     if(Mid>=R)return Query_lx(c[x].l,l,Mid,L,R);
65     if(Mid<L)return Query_lx(c[x].r,Mid+1,r,L,R);
66     return Max(Query_lx(c[x].l,l,Mid,L,R),Query_sum(c[x].l,l,Mid,L,R)+Query_lx(c[x].r,Mid+1,r,L,R));
67 }
68 int main(){
69     scanf("%d",&n);
70     for(i=1;i<=n;i++)scanf("%d",&b[i].w),b[i].f=i;
71     sort(b+1,b+n+1,Cmp);
72     w[1]=b[1].w;
73     a[b[1].f]=m=1;
74     g[1].push_back(b[1].f);
75     for(i=2;i<=n;i++){
76         if(b[i].w==b[i-1].w)a[b[i].f]=m;else a[b[i].f]=++m,w[m]=b[i].w;
77         g[m].push_back(b[i].f);
78     }
79     Build(Rt[1],1,n);
80     for(i=1;i<m;i++){
81         Rt[i+1]=Rt[i];
82         for(j=0;j<g[i].size();j++)
83         Update(Rt[i+1],Rt[i+1],1,n,g[i][j]);
84     }
85     scanf("%d",&Q);
86     while(Q--){
87         for(i=1;i<=4;i++)scanf("%d",&q[i]),q[i]=(q[i]+w[Ans])%n+1;
88         sort(q+1,q+5);
89         l=1;r=m;
90         while(l<=r){
91             Mid=l+r>>1;
92             if(Query_sum(Rt[Mid],1,m,q[2],q[3])+Query_rx(Rt[Mid],1,m,q[1],q[2]-1)+Query_lx(Rt[Mid],1,m,q[3]+1,q[4])>=0)Ans=Mid,l=Mid+1;else r=Mid-1;
93         }
94         printf("%d\n",w[Ans]);
95     }
96     return 0;
97 }
bzoj2653

 

以上是关于bzoj2653 -- 二分+主席树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2653: middle 主席树 二分

bzoj 2653 middle (主席树+二分)

BZOJ 2653 middle | 主席树

BZOJ 2653: middle [主席树 中位数]

bzoj2653: middle

bzoj2653: middle