一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
我会使用一些方式强制你在线。
一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
我会使用一些方式强制你在线。
第一行序列长度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]。
输入保证满足条件。
Q行依次给出询问的答案。
0:n,Q<=100
1,...,5:n<=2000
0,...,19:n<=20000,Q<=25000
#include "stdio.h" #include "iostream" #include "stdlib.h" #include "algorithm" using namespace std; const int N=20005,Lg=17; struct node { int l,r; int val; int lmx,rmx,sum; node * s[2]; inline void ins(int _l,int _r,node* lson,node* rson){ l=_l; r=_r; s[0]=lson; s[1]=rson; } inline void make (int v){ val=lmx=rmx=sum=v;} } ptree[Lg*N]; //表示主席树的点集 node* root[N]; //N个版本的根结点所在位置 int readin[N],sorted[N],n,tmp; //分别表示排序和没排序的 int past[N]; //原来所在的位置 inline void push_up(int v){ node * c=ptree+v; c->sum=c->s[0]->sum+c->s[1]->sum; c->lmx=max(c->s[0]->lmx,c->s[0]->sum+c->s[1]->lmx); c->rmx=max(c->s[1]->rmx,c->s[1]->sum+c->s[0]->rmx); } node* Build (int l,int r){ int k=++tmp; ptree[k].l=l; ptree[k].r=r; if (l==r) { ptree[k].make(1); return ptree+k; } int mid=(l+r)>>1; ptree[k].ins(l,r,Build(l,mid),Build(mid+1,r)); push_up(k); return ptree+k; } node* build_next (node *last,int l,int r,int edit){ int k=++tmp; ptree[k].l=l; ptree[k].r=r; if (l==r) { ptree[k].make(-1); return ptree+k; } int mid=(l+r)>>1; if (edit<=mid) ptree[k].ins (l,r,build_next(last->s[0],l,mid,edit),last->s[1]); else ptree[k].ins (l,r,last->s[0],build_next(last->s[1],mid+1,r,edit)); push_up(k); return ptree+k; } void init(){ scanf("%d",&n); int i; for (i=1;i<=n;i++) scanf("%d",&readin[i]); for (i=1;i<=n;i++) sorted[i]=readin[i]; sort(sorted+1,sorted+n+1); for (i=1;i<=n;i++){ int bot=1,top=n,mid=(1+n)>>1; while (bot<top){ if (sorted[mid]==readin[i]) break; if (sorted[mid]>readin[i]) top=mid-1; else bot=mid+1; mid=(top+bot)>>1; } past[mid]=i; } root[1]= Build (1,n); for (i=2;i<=n;i++) root[i]= build_next (root[i-1],1,n,past[i-1]); } int query_sum (node *srt,int l,int r){ int _l=srt->l,_r=srt->r,mid=(_l+_r)>>1; if(_l==_r||(_l==l&&_r==r)) return srt->sum; if (r<=mid) return query_sum(srt->s[0],l,r); if (l>mid) return query_sum(srt->s[1],l,r); return query_sum(srt->s[0],l,mid)+ query_sum(srt->s[1],mid+1,r); } int query_lmx (node *srt,int l,int r){ int _l=srt->l,_r=srt->r,mid=(_l+_r)>>1; if(_l==_r||(_l==l&&_r==r)) return srt->lmx; if (r<=mid) return query_lmx(srt->s[0],l,r); if (l>mid) return query_lmx(srt->s[1],l,r); int a=query_lmx(srt->s[0],l,mid); a=max (a,query_sum(srt->s[0],l,mid)+ query_lmx(srt->s[1],mid+1,r)); return a; } int query_rmx (node *srt,int l,int r){ int _l=srt->l,_r=srt->r,mid=(_l+_r)>>1; if(_l==_r||(_l==l&&_r==r)) return srt->rmx; if (r<=mid) return query_rmx(srt->s[0],l,r); if (l>mid) return query_rmx(srt->s[1],l,r); int a=query_rmx(srt->s[1],mid+1,r); a=max (a,query_sum(srt->s[1],mid+1,r)+ query_rmx(srt->s[0],l,mid)); return a; } bool check(int al,int ar,int bl,int br,int k){ //第k版本的线段树的al~br的最大子段和 且必须包含ar~bl段 int x; if (ar+1<bl) x = query_sum(root[k],ar+1,bl-1); else x = 0; x+= query_rmx(root[k],al,ar); x+= query_lmx(root[k],bl,br); return x>=0; } int query(int al,int ar,int bl,int br){ int bot=1,top=n,mid=(1+n)>>1; while (bot<top){ if (check(al,ar,bl,br,mid)) bot=mid; else top=mid-1; mid=(top+bot+1)>>1; } return sorted[mid]; } void work(){ int q,i,x=0; scanf("%d",&q); int t[5],j; for (i=1;i<=q;i++){ scanf("%d%d%d%d",t,t+1,t+2,t+3); for (j=0;j<4;j++) t[j]=(t[j]+x)%n+1; sort(t,t+4); printf("%d\n",x=query(t[0],t[1],t[2],t[3])); } } int main(){ init(); work(); return 0; }