bzoj2653: middle
首先,对于每个询问,我们二分答案
然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1
那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁
这个区间和呢,我们可以用主席树维护前缀和
[c,d]上的最大前缀和减去[a-1,b-1]上的最小前缀和,就是所有可用区间的最大区间和
这样要求主席树支持区间修改,正好之前没写过(捂脸),练一下
复杂度O(nlog^2n)
(如果不资磁区间修改的话,也可以通过维护最大/小连续和的那套理论,达到同样的效果(好像所有题解都是这么做的))
(当然首先要离散化……)
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> #define N 23333 using namespace std; inline int read(){ int ret=0;char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while ('0'<=ch&&ch<='9'){ ret=ret*10-48+ch; ch=getchar(); } return ret; } struct STnode{ int ls,rs; int maxv,minv; int tag; }; int n,root[N]; struct SegmentTree{ STnode t[12333666]; int size; inline int newnode(int x){t[++size]=t[x];return size;} void PushUp(int x){ t[x].maxv=max(t[t[x].ls].maxv,t[t[x].rs].maxv); t[x].minv=min(t[t[x].ls].minv,t[t[x].rs].minv); } void add(int &x,int delta){ x=newnode(x); t[x].maxv+=delta;t[x].minv+=delta;t[x].tag+=delta; } void PushDown(int x){ if (!t[x].ls) t[x].tag=0; if (t[x].tag){ add(t[x].ls,t[x].tag);add(t[x].rs,t[x].tag); t[x].tag=0; } } void build(int x,int l,int r){ t[x].tag=t[x].ls=t[x].rs=0; if ((t[x].minv=l)==(t[x].maxv=r)) return; int mid=(l+r)/2; build(t[x].ls=++size,l,mid); build(t[x].rs=++size,mid+1,r); } int clear(){build(size=1,1,n);return 1;} void modify(int &x,int L,int R,int l,int r,int delta){ PushDown(x); if (l<=L&&R<=r){add(x,delta);return;} x=newnode(x); int mid=(L+R)/2; if (l<=mid) modify(t[x].ls,L,mid,l,r,delta); if (r>mid) modify(t[x].rs,mid+1,R,l,r,delta); PushUp(x); } int qmin(int x,int L,int R,int l,int r){ PushDown(x); if (l<=L&&R<=r) return t[x].minv; int mid=(L+R)/2; if (r<=mid) return qmin(t[x].ls,L,mid,l,r); if (l>mid) return qmin(t[x].rs,mid+1,R,l,r); return min(qmin(t[x].ls,L,mid,l,r),qmin(t[x].rs,mid+1,R,l,r)); } int qmax(int x,int L,int R,int l,int r){ PushDown(x); if (l<=L&&R<=r) return t[x].maxv; int mid=(L+R)/2; if (r<=mid) return qmax(t[x].ls,L,mid,l,r); if (l>mid) return qmax(t[x].rs,mid+1,R,l,r); return max(qmax(t[x].ls,L,mid,l,r),qmax(t[x].rs,mid+1,R,l,r)); } } st; int query(int a,int b,int c,int d){ int l=1,r=n+1,mid; while (l+1<r){ mid=(l+r)/2; int tmpr=st.qmax(root[mid],1,n,c,d); int tmpl=st.qmin(root[mid],1,n,max(a-1,1),b-1); if (a==1) tmpl=min(tmpl,0); if (tmpr-tmpl>=0) l=mid; else r=mid; } return l; } int a[N]; struct num{ int value,pos; num(){} num(int _value,int _pos):value(_value),pos(_pos){} } tt[N]; inline bool operator <(const num &x,const num &y){ return x.value<y.value; } int main(){ n=read(); for (int i=1;i<=n;++i) tt[i]=num(a[i]=read(),i); sort(tt+1,tt+n+1); root[1]=st.clear(); for (int i=1;i<n;++i) st.modify(root[i+1]=root[i],1,n,tt[i].pos,n,-2); int lastans=0,q[4]; for (int Q=read();Q;Q--){ for (int k=0;k<4;++k) q[k]=(read()+lastans)%n+1; sort(q,q+4); lastans=tt[query(q[0],q[1],q[2],q[3])].value; printf("%d\n",lastans); } return 0; }