• bzoj2653: middle


    Description

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

    Input

    第一行序列长度n。接下来n行按顺序给出a中的数。
    接下来一行Q。然后Q行每行a,b,c,d,我们令上个询问的答案是
    x(如果这是第一个询问则x=0)。
    令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
    将q从小到大排序之后,令真正的
    要询问的a=q[0],b=q[1],c=q[2],d=q[3]。  
    输入保证满足条件。
    第一行所谓“排过序”指的是从大到小排序!

    Output

    Q行依次给出询问的答案。

    对序列中每个数x用可持久化线段树预处理出一个新数列b,其中b[i]=a[i]>=a[x]?1:-1

    这样就可以在查询时二分答案,左右端点分别在指定区间内的最大子段和>=0则可行

    #include<bits/stdc++.h>
    const int N=20007;
    char buf[N*100],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr,f=1;
        while(c<48)c=='-'&&(f=-1),c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x*f;
    }
    int n,a[N],id[N],la=0;
    bool cmp(int x,int y){
        return a[x]<a[y];
    }
    int max(int a,int b){return a>b?a:b;}
    void maxs(int&a,int b){if(a<b)a=b;}
    int l,r,s0,s1;
    struct node{
        node*lc,*rc;
        int L,R,M,ls,rs,s;
        void up(){
            s=lc->s+rc->s;
            ls=max(lc->ls,lc->s+rc->ls);
            rs=max(rc->rs,rc->s+lc->rs);
        }
        void sum(){
            if(l<=L&&R<=r){
                s0+=s;
                return;
            }
            if(l<=M)lc->sum();
            if(r>M)rc->sum();
        }
        void lms(){
            if(l<=L&&R<=r){
                maxs(s0,ls+s1);
                s1+=s;
                return;
            }
            if(l<=M)lc->lms();
            if(r>M)rc->lms();
        }
        void rms(){
            if(l<=L&&R<=r){
                maxs(s0,rs+s1);
                s1+=s;
                return;
            }
            if(r>M)rc->rms();
            if(l<=M)lc->rms();
        }
        node*chg(int x);
    }ns[N*20],*np=ns,*rt[N];
    node*node::chg(int x){
        node*w=np++;
        *w=*this;
        if(~M){
            if(x<=M)w->lc=lc->chg(x);
            else w->rc=rc->chg(x);
            w->up();
        }else w->ls=w->rs=0,w->s=-1;
        return w;
    }
    node*build(int L,int R){
        node*w=np++;
        w->L=L;w->R=R;
        if(L<R){
            int M=w->M=L+R>>1;
            w->lc=build(L,M);
            w->rc=build(M+1,R);
            w->up();
        }else w->ls=w->rs=w->s=1,w->M=-1;
        return w;
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin)[buf]=0;
        n=_();
        for(int i=0;i<n;++i)a[id[i]=i]=_();
        std::sort(id,id+n,cmp);
        rt[0]=build(0,n-1);
        for(int i=1;i<n;++i){
            rt[i]=rt[i-1]->chg(id[i-1]);
        }
        for(int m=_();m;--m){
            int q[4];
            for(int i=0;i<4;++i)q[i]=(_()+la)%n;
            std::sort(q,q+4);
            int L=0,R=n-1,M,ans;
            while(L<R){
                M=L+R+1>>1;
                ans=0;
                s0=0,s1=0,l=q[0],r=q[1]-1;
                rt[M]->rms();
                ans+=s0;
                s0=0,s1=0,l=q[2]+1,r=q[3];
                rt[M]->lms();
                ans+=s0;
                s0=0,s1=0,l=q[1],r=q[2];
                rt[M]->sum();
                ans+=s0;
                if(ans>=0)L=M;
                else R=M-1;
            }
            printf("%d
    ",la=a[id[L]]);
        }
        return 0;
    }
  • 相关阅读:
    决策树算法系列之一 ID3
    线性递归数列算法题
    Python爬虫快速上手教程
    gensim快速上手教程
    GCN和GCN在文本分类中应用
    命名实体如何进行概念消歧?
    浅谈神经网络中的激活函数
    nginx安装配置和基本使用
    netty学习总结(三)
    netty学习总结(二)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6579957.html
Copyright © 2020-2023  润新知