BZOJ 2653: middle|主席树

来源:互联网 发布:焦作淘宝网络公司 编辑:程序博客网 时间:2024/06/05 22:38

这题思路确实比较难想!建主席树也是非常的特别!
考虑二分答案,如果当前check的答案是x那么大于等于x的数的贡献是1,其余的贡献是-1,然后就判断一下是否存在总贡献>=0的区间,判断的话需要对所有的数建立一个线段树,然后直接建会MLE+TLE,然后就需要我们的黑科技可持久化的数据结构主席树,先把所有的位置都设为1,然后把数排序后从小到大建树每次-1。
非常神的建树方式,从小到大插入数,插入的权值是这个数的位置!!!
正好和我们的正常思路反着…

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>#define ll unsigned long long#define N 20022#define mx 1e9using namespace std;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}struct W{int v,pos;}h[N];int sum[N*500],lmx[N*500],rmx[N*500],ch[N*500][2];int root[N],q[4];int n,m,cnt,ans;bool cmp(W a,W b){return a.v<b.v;}void push_up(int x){    sum[x]=sum[ch[x][0]]+sum[ch[x][1]];    lmx[x]=max(lmx[ch[x][0]],sum[ch[x][0]]+lmx[ch[x][1]]);    rmx[x]=max(rmx[ch[x][1]],sum[ch[x][1]]+rmx[ch[x][0]]);}void build(int &x,int l,int r){    if(!x)x=++cnt;    if(l==r)    {        sum[x]=lmx[x]=rmx[x]=1;        return;    }    int mid=l+r>>1;    build(ch[x][0],l,mid);    build(ch[x][1],mid+1,r);    push_up(x);}void add(int pre,int &x,int l,int r,int v,int f){    if(!x)x=++cnt;    if(l==r)    {        lmx[x]=rmx[x]=sum[x]=f;        return;    }    int mid=l+r>>1;    if(v<=mid)        ch[x][1]=ch[pre][1],add(ch[pre][0],ch[x][0],l,mid,v,f);    else        ch[x][0]=ch[pre][0],add(ch[pre][1],ch[x][1],mid+1,r,v,f);    push_up(x);}int ask_all(int x,int L,int R,int l,int r){    if(L==l&&R==r)return sum[x];    int mid=L+R>>1;    if(r<=mid)return ask_all(ch[x][0],L,mid,l,r);    else if(l>mid)return ask_all(ch[x][1],mid+1,R,l,r);    return ask_all(ch[x][0],L,mid,l,mid)+ask_all(ch[x][1],mid+1,R,mid+1,r);}int ask_left(int x,int L,int R,int l,int r){    if(L==l&&R==r)return lmx[x];    int mid=L+R>>1;    if(r<=mid)return ask_left(ch[x][0],L,mid,l,r);    else if(l>mid)return ask_left(ch[x][1],mid+1,R,l,r);    return max(ask_left(ch[x][0],L,mid,l,mid),ask_all(ch[x][0],L,mid,l,mid)+ask_left(ch[x][1],mid+1,R,mid+1,r));}int ask_right(int x,int L,int R,int l,int r){    if(L==l&&R==r)return rmx[x];    int mid=L+R>>1;    if(r<=mid)return ask_right(ch[x][0],L,mid,l,r);    else if(l>mid)return ask_right(ch[x][1],mid+1,R,l,r);    return max(ask_right(ch[x][1],mid+1,R,mid+1,r),ask_all(ch[x][1],mid+1,R,mid+1,r)+ask_right(ch[x][0],L,mid,l,mid));}bool check(int x,int a,int b,int c,int d){    int sum=ask_left(root[x],1,n,c,d)+ask_right(root[x],1,n,a,b);    if(b+1<c) sum+=ask_all(root[x],1,n,b+1,c-1);    return sum>=0;}int main(){    n=sc();    for(int i=1;i<=n;i++)        h[i].v=sc(),        h[i].pos=i;    sort(h+1,h+n+1,cmp);    build(root[1],1,n);    for(int i=2;i<=n;i++)        add(root[i-1],root[i],1,n,h[i-1].pos,-1);    m=sc();    for(int i=1;i<=m;i++)    {        for(int j=0;j<4;j++)            q[j]=(sc()+ans)%n+1;        sort(q,q+4);        int l=1,r=n;ans=1;        while(l<=r)        {            int mid=l+r>>1;            if(check(mid,q[0],q[1],q[2],q[3]))ans=mid,l=mid+1;            else r=mid-1;        }        printf("%d\n",ans=h[ans].v);    }    return 0;}
0 0
原创粉丝点击