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; }