码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2653: middle

时间:2017-03-19 14:24:47      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:content   return   fread   struct   put   排序   else   序列   nbsp   

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\n",la=a[id[L]]);
    }
    return 0;
}

 

bzoj2653: middle

标签:content   return   fread   struct   put   排序   else   序列   nbsp   

原文地址:http://www.cnblogs.com/ccz181078/p/6579957.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!