http://www.lydsy.com/JudgeOnline/problem.php?id=2653
题目描述:
给长度为20000的序列。求左端点在[a,b]和右端点在[c,d]中所有的子序列,最大的中位数。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 20005; struct info{ int sum, mxl, mxr; info(){} info(int val){ sum = mxl = mxr = val; } }; info operator + (const info l, const info r){ info mid ; mid .sum = l.sum + r.sum; mid .mxl = max(l.mxl , l.sum + max(r.mxl, 0 )); mid .mxr = max(r.mxr , r.sum + max(l.mxr, 0 )); return mid; } struct tree{ int l,r; tree *pl, *pr; info v; tree (int _l, int _r, tree *_pl, tree *_pr) : l(_l), r(_r), pl (_pl), pr(_pr){ v = pl->v + pr->v; } tree (int _l, int _r, int val): l(_l), r(_r){ if(_l == _r) { v = info(val); return ; } int mid = l + r >>1; pl = new tree(l, mid, val); pr = new tree(mid+1, r, val); v = pl->v + pr->v; } info ask(int L,int R){ if(L <= l && R >= r){ return v; } int mid = l + r >> 1; if(mid < L) return pr->ask(L,R); else if(mid >= R) return pl->ask(L,R); else return pl ->ask(L,R) + pr ->ask(L,R); } tree* change(int pos, int val){ if(l == r){ return new tree(l,r,val); } int mid = l+r >>1; if(pos <= mid) return new tree(l,r,pl->change(pos,val),pr); return new tree(l,r,pl,pr->change(pos,val)); } void OP(){ cout<<l<<" "<<r<<" "<<v.mxl<<" "<<v.sum<<" "<<v.mxr<<endl; if(l==r) return; pl->OP(); pr->OP(); } }; tree *root[N]; pair<int,int> num[N]; int a[N],n; bool chk(int m,int a,int b,int c,int d){ tree *rt = root[m]; int val = rt->ask(a, b).mxr + (b+1<c ? rt->ask(b+1,c-1).sum : 0) + rt -> ask(c,d).mxl ; return val >= 0; } int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); num[i] = make_pair(a[i],i); } sort(num,num+n); root[0] = new tree(0,n-1,1); for(int i=1;i<n;i++){ root[i] = root[i-1] -> change(num[i-1].second, -1); } int Q, last = 0; cin >>Q; while(Q--){ int q[4]; for(int i=0;i<4;i++){ scanf("%d",&q[i]); q[i] = (q[i] + last) % n; } sort(q,q+4); int l = 0, r = n; while(l < r){ int m = l+ r>>1; if(chk(m,q[0],q[1],q[2],q[3])) l = m+1; else r = m; } printf("%d\n",num[l-1].first); last = num[l-1].first; } return 0; }