读书人

Bzoj 2653 middle(2分+主席树)

发布时间: 2013-02-18 10:50:49 作者: rapoo

Bzoj 2653 middle(二分+主席树)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove

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

http://www.lydsy.com/JudgeOnline/problem.php?id=2653

CLJ的题,强制在线处理了。

要求中位数最大,首先二分中位数,然后判断可行不可行。

判断X可行不可行,对于区间内的数,凡是>=X的标为1,否则为-1。这样的话,求一次最大区间和

如果大于等于0,则说明可行。

检验一下就很明白了。

这就是关键了,不过不能每次去暴力。快速求解子段和可以用线段树解决 ,但是对于不同的X,不可能建立多棵线段树

这就可以用主席树解决

对于初始的数,可以离散化,也可以不需要,直接排序,然后按从小到大依次建立主席树。

初始的话全为1,然后不断修改-1。有了之前的可持久化的基础,这步就很轻松了

然后就类似线段树一样,维护一个区间和,最大的左连续和,最大的右连续和。

结合在一起的时候,debug了下。。。。弱爆了

#include<iostream>  #include<cstdio>  #include<map>  #include<cstring>  #include<cmath>  #include<vector>  #include<algorithm>  #include<set>  #include<stack>#include<string>  #include<ctime>#include<queue>  #include<cassert>#define inf 1000000005  #define M 2560005 #define N 20005#define maxn 210005  #define eps 1e-8#define zero(a) fabs(a)<eps  #define Min(a,b) ((a)<(b)?(a):(b))  #define Max(a,b) ((a)>(b)?(a):(b))  #define pb(a) push_back(a)  #define mp(a,b) make_pair(a,b)  #define mem(a,b) memset(a,b,sizeof(a))  #define LL long long  #define MOD 1000000007#define sqr(a) ((a)*(a))  #define Key_value ch[ch[root][1]][0]  #define test puts("OK");  #define pi acos(-1.0)#define lowbit(x) ((-(x))&(x))#define HASH1 1331#define HASH2 10001#define C   240  #define vi vector<int>#define TIME 10  #pragma comment(linker, "/STACK:1024000000,1024000000")  using namespace std;int a[N],n,q;int T[M],lson[M],rson[M],sum[M],lx[M],rx[M],tot=0;pair<int,int>h[N];void Push_up(int root){    int l=lson[root];    int r=rson[root];    sum[root]=sum[l]+sum[r];    lx[root]=max(lx[l],sum[l]+lx[r]);    rx[root]=max(rx[r],sum[r]+rx[l]);}int bulid(int l,int r){    int root=tot++;    if(l==r){        lx[root]=rx[root]=sum[root]=1;        return root;    }    int mid=(l+r)>>1;    lson[root]=bulid(l,mid);    rson[root]=bulid(mid+1,r);    Push_up(root);    return root;}int update(int root,int l,int r,int pos,int val){    int newroot=tot++;    if(l==r){        sum[newroot]=lx[newroot]=rx[newroot]=val;        return newroot;    }    int mid=(l+r)>>1;      if(pos<=mid){        lson[newroot]=update(lson[root],l,mid,pos,val);        rson[newroot]=rson[root];            root=lson[root];      }    else{            rson[newroot]=update(rson[root],mid+1,r,pos,val);         lson[newroot]=lson[root];            root=rson[root];        }      Push_up(newroot);    return newroot;  }int query_all(int root,int L,int R,int l,int r){    if(l==L&&r==R) return sum[root];    int mid=(L+R)>>1;    if(r<=mid) return query_all(lson[root],L,mid,l,r);    else if(l>mid) return query_all(rson[root],mid+1,R,l,r);    else return query_all(lson[root],L,mid,l,mid)+query_all(rson[root],mid+1,R,mid+1,r);}int query_left(int root,int L,int R,int l,int r){    if(l==L&&r==R) return lx[root];    int mid=(L+R)>>1;    if(r<=mid) return query_left(lson[root],L,mid,l,r);    else if(l>mid) return query_left(rson[root],mid+1,R,l,r);    else return max(query_left(lson[root],L,mid,l,mid),query_all(lson[root],L,mid,l,mid)+query_left(rson[root],mid+1,R,mid+1,r));}int query_right(int root,int L,int R,int l,int r){    if(l==L&&r==R) return rx[root];    int mid=(L+R)>>1;    if(r<=mid) return query_right(lson[root],L,mid,l,r);    else if(l>mid) return query_right(rson[root],mid+1,R,l,r);    else return max(query_right(rson[root],mid+1,R,mid+1,r),query_all(rson[root],mid+1,R,mid+1,r)+query_right(lson[root],L,mid,l,mid));}int check(int k,int a,int b,int c,int d){    int val=0;    if(b+1<c) val+=query_all(T[k],0,n-1,b+1,c-1);    val+=query_right(T[k],0,n-1,a,b);    val+=query_left(T[k],0,n-1,c,d);    return val>=0;}void debug(int root,int l,int r){    cout<<l<<" "<<r<<" "<<sum[root]<<endl;    if(l!=r){        int m=(l+r)>>1;        debug(lson[root],l,m);        debug(rson[root],m+1,r);    }}int main(){    scanf("%d",&n);    for(int i=0;i<n;i++){        scanf("%d",&a[i]);        h[i]=mp(a[i],i);    }    sort(h,h+n);    T[0]=bulid(0,n-1);    for(int i=1;i<n;i++)        T[i]=update(T[i-1],0,n-1,h[i-1].second,-1);    scanf("%d",&q);    int ans=0,p[4];    while(q--){        scanf("%d%d%d%d",&p[0],&p[1],&p[2],&p[3]);        for(int i=0;i<4;i++)            p[i]=(p[i]+ans)%n;        sort(p,p+4);        int low=0,high=n-1,mid,ret;        while(low<=high){            mid=(low+high)>>1;            if(check(mid,p[0],p[1],p[2],p[3])){                low=mid+1;                ret=mid;            }            else                high=mid-1;        }        ans=h[ret].first;        printf("%d\n",ans);    }    return 0;}


读书人网 >编程

热点推荐