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; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步