设有 m+1 ( m 为离散化后序列中不同数的个数)棵线段树,分别为第 0 棵到第 m 棵,第 i 棵线段树储存当 >i 的数改成 1 , ≤i 的数改成 −1 后的区间和、最大前缀和、最大后缀和
那么查询(1)(3)就只需要在第 mid−1 棵线段树上查询下区间最大后缀 / 前缀和即可
O(nlog2n)
Code
#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define For(i, a, b) for (i = a; i <= b; i++)inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Max(const T &a,const T &b){return a > b ? a : b;}constint N =2e4+5, L =7e6+5;int n, a[N], m, b[N], rt[N], q, tmp[4], lst, ToT, pos[N];struct xpair
{int x, y;} qa[N];struct tri
{int sum, pre, suf;friendinline tri operator+(tri a, tri b){return(tri){a.sum + b.sum,Max(a.pre, a.sum + b.pre),Max(b.suf, b.sum + a.suf)};}};inlineboolcomp(xpair a, xpair b){return a.y < b.y;}struct node
{int lc, rc; tri a;} T[L];voidchange(int l,int r,int pos,int v,int&p){if(!p) p =++ToT;if(l == r)return(void)(T[p].a.sum = T[p].a.pre = T[p].a.suf = v);int mid = l + r >>1;if(pos <= mid)change(l, mid, pos, v, T[p].lc);elsechange(mid +1, r, pos, v, T[p].rc);
T[p].a = T[T[p].lc].a + T[T[p].rc].a;}voidchangeof(int y,int&x,int l,int r,int pos,int v){
T[x =++ToT]= T[y];if(l == r)return(void)(T[x].a.sum = T[x].a.pre = T[x].a.suf = v);int mid = l + r >>1;if(pos <= mid)changeof(T[y].lc, T[x].lc, l, mid, pos, v);elsechangeof(T[y].rc, T[x].rc, mid +1, r, pos, v);
T[x].a = T[T[x].lc].a + T[T[x].rc].a;}
tri query(int l,int r,int s,int e,int p){if(s > e)return(tri){0,0,0};if(l == s && r == e)return T[p].a;int mid = l + r >>1;if(e <= mid)returnquery(l, mid, s, e, T[p].lc);elseif(s >= mid +1)returnquery(mid +1, r, s, e, T[p].rc);elsereturnquery(l, mid, s, mid, T[p].lc)+query(mid +1, r, mid +1, e, T[p].rc);}boolcheck(int a,int b,int c,int d,int mid){returnquery(1, n, a, b, rt[pos[mid -1]]).suf
+query(1, n, b +1, c -1, rt[pos[mid -1]]).sum
+query(1, n, c, d, rt[pos[mid -1]]).pre >=0;}intmain(){int i;
n =read();
For (i,1, n) a[i]= b[i]=read();
std::sort(b +1, b + n +1);
m = std::unique(b +1, b + n +1)- b -1;
For (i,1, n) a[i]= std::lower_bound(b +1, b + m +1, a[i])- b;
For (i,1, n) qa[i]=(xpair){i, a[i]};
std::sort(qa +1, qa + n +1, comp);
For (i,1, n)change(1, n, i,1, rt[0]);
For (i,1, n){changeof(rt[i -1], rt[i],1, n, qa[i].x,-1);
pos[qa[i].y]= i;}
q =read();while(q--){
tmp[0]=(read()+ lst)% n +1;
tmp[1]=(read()+ lst)% n +1;
tmp[2]=(read()+ lst)% n +1;
tmp[3]=(read()+ lst)% n +1;
std::sort(tmp, tmp +4);int l =1, r = m;while(l <= r){int mid = l + r >>1;if(check(tmp[0], tmp[1], tmp[2], tmp[3], mid)) l = mid +1;else r = mid -1;}printf("%d\n", lst = b[r]);}return0;}