jzoj2902 集訓隊互測 2012 Middle 可持久化線段樹 __jzoj

來源:互聯網
上載者:User
題目大意 一個長度為 n 的序列 a ,設其排過序之後為 b ,其中位元定義為 b[n/2] ,其中 a,b 從 0 開始標號 , 除法取下整。 給你一個長度為 n 的序列 s 。回答 Q 個這樣的詢問 : s 的左端點在 [a,b] 之間 , 右端點在 [c,d] 之間的子序列中 ,最大的中位元。 其中 a<b<c<d a。 位置也從 0 開始標號。 我會使用一些方式強制你線上。 解題思路 考慮求一個區間裡的中位元,我們會二分答案,檢查大於等於答案減小於答案的個數,如果大於等於0答案就有可能更大,越大答案就越大。那我們發現[b+1,c-1]一定要取,[a,b]取右數最大值,[c,d]取左數最大值,加起來就可以調整答案。 假設當前答案為x,那我們把大於等於x的位置都標為1,小於的位置標為-1就可以用線段樹維護以上資訊。我們發現不同的答案只有n個,我們對每一個x都維護一顆線段樹即可,發現相鄰兩個x不同權值的位置有一個,那我們可以按x的大小順序建線段樹,利用之前的資訊就可以快速求出當前線段樹,用可持久化線段樹即可。 code
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define Min(a,b) ((a<b)?a:b)#define Max(a,b) ((a>b)?a:b)#define Fo(i,j,k) for(int i=j;i<=k;i++)#define Fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const Mxn=2*1e4,Mxnm=1e5;int N,Pon,A[Mxn+9],B[Mxn+9],C[9],T[Mxn*20+9][3],Son[Mxn*20+9][2];bool Cmp(int X,int Y){return A[X]<A[Y];}void Update(int Now){    T[Now][0]=T[Son[Now][0]][0]+T[Son[Now][1]][0];    T[Now][1]=Max(T[Son[Now][0]][1],T[Son[Now][0]][0]+T[Son[Now][1]][1]);    T[Now][2]=Max(T[Son[Now][1]][2],T[Son[Now][0]][2]+T[Son[Now][1]][0]);}void Build(int Now,int L,int R){    if(L==R){        T[Now][0]=T[Now][1]=T[Now][2]=1;        return;    }    int Mid=(L+R)>>1;    Son[Now][0]=++Pon;Son[Now][1]=++Pon;    Build(Son[Now][0],L,Mid);Build(Son[Now][1],Mid+1,R);    Update(Now);}void Oper(int Pre,int Now,int L,int R,int V){    if(L==R){        T[Now][0]=T[Now][1]=T[Now][2]=-1;        return;    }    int Mid=(L+R)>>1;    if(V<=Mid){        Son[Now][1]=Son[Pre][1];        Son[Now][0]=++Pon;        Oper(Son[Pre][0],Son[Now][0],L,Mid,V);    }else{        Son[Now][0]=Son[Pre][0];        Son[Now][1]=++Pon;        Oper(Son[Pre][1],Son[Now][1],Mid+1,R,V);    }    Update(Now);}int Qury(int Now,int L,int R,int L1,int R1,int Op){    int Mid=(L+R)>>1;    if((L==L1)&&(R==R1))return T[Now][Op];    else if(R1<=Mid)return Qury(Son[Now][0],L,Mid,L1,R1,Op);    else if(Mid<L1)return Qury(Son[Now][1],Mid+1,R,L1,R1,Op);    else if(!Op)return Qury(Son[Now][0],L,Mid,L1,Mid,Op)                                +Qury(Son[Now][1],Mid+1,R,Mid+1,R1,Op);    else if(Op==1){        int X1=Qury(Son[Now][0],L,Mid,L1,Mid,Op),            X2=Qury(Son[Now][0],L,Mid,L1,Mid,0)            +Qury(Son[Now][1],Mid+1,R,Mid+1,R1,Op);        return Max(X1,X2);    }else{        int X1=Qury(Son[Now][0],L,Mid,L1,Mid,Op)+            Qury(Son[Now][1],Mid+1,R,Mid+1,R1,0),            X2=Qury(Son[Now][1],Mid+1,R,Mid+1,R1,Op);        return Max(X1,X2);    }}int main(){    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d",&N);Pon=N;    Fo(i,1,N)scanf("%d",&A[i]),B[i]=i;    sort(B+1,B+N+1,Cmp);    Build(1,1,N);    Fo(i,2,N)Oper(i-1,i,1,N,B[i-1]);    int Q,Last=0;scanf("%d",&Q);    Fo(cas,1,Q){        Fo(i,1,4)scanf("%d",&C[i]),C[i]=(C[i]+Last)%N+1;        sort(C+1,C+5);        int L=1,R=N,Mid;        while(L!=R){            Mid=(L+R+1)>>1;            if(Qury(Mid,1,N,C[1],C[2],2)+Qury(Mid,1,N,C[3],C[4],1)                +((C[2]+1!=C[3])?Qury(Mid,1,N,C[2]+1,C[3]-1,0):0)>=0)L=Mid;            else R=Mid-1;        }        printf("%d\n",Last=A[B[L]]);    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.