点击查看
solution
简单口胡一下就跑
考虑二分答案
a
n
s
ans
ans
区间
[
x
1
,
x
2
]
,
x
1
∈
[
a
,
b
]
,
x
2
∈
[
c
,
d
]
[x1,x2],x1∈[a,b],x2∈[c,d]
[x1,x2],x1∈[a,b],x2∈[c,d]
大于等于
a
n
s
ans
ans的设为
1
1
1,小于
a
n
s
ans
ans的设为
0
0
0
如果和
≥
0
\ge 0
≥0表示
a
n
s
ans
ans还可以更大,否则应该变小
发现无论
x
1
,
x
2
x1,x2
x1,x2怎么取,有一段是肯定包含的
→
[
b
+
1
,
c
−
1
]
\rightarrow[b+1,c-1]
→[b+1,c−1]
即,只需要最大化
[
x
1
,
b
]
,
[
c
,
x
2
]
[x1,b],[c,x2]
[x1,b],[c,x2]之间的和,就是一个最大后缀/最大前缀问题
可以利用线段树求解
对于每一个中位数建立一棵线段树
发现空间飞了
主席树硬刚
值域远大于
“
“
“定义域
”
”
”
离散搞
t
a
ta
ta
详情请见下方代码
⇓
\Downarrow
⇓
code
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
#define maxn 20005
int n, m, cnt;
int opt[10], root[maxn];
struct array { int val, id; }a[maxn];
struct node { int sum, lsum, rsum, lson, rson; }t[maxn * 30];
void pushup( int x ) {
t[x].sum = t[t[x].lson].sum + t[t[x].rson].sum;
t[x].lsum = max( t[t[x].lson].lsum, t[t[x].lson].sum + t[t[x].rson].lsum );
t[x].rsum = max( t[t[x].rson].rsum, t[t[x].rson].sum + t[t[x].lson].rsum );
}
void build( int &now, int l, int r ) {
now = ++ cnt;
t[now].sum = t[now].lsum = t[now].rsum = r - l + 1;
if( l == r ) return;
int mid = ( l + r ) >> 1;
build( t[now].lson, l, mid );
build( t[now].rson, mid + 1, r );
}
void modify( int lst, int &now, int l, int r, int pos ) {
t[now = ++ cnt] = t[lst];
if( l == r ) { t[now].sum = t[now].lsum = t[now].rsum = -1; return; }
int mid = ( l + r ) >> 1;
if( pos <= mid ) modify( t[lst].lson, t[now].lson, l, mid, pos );
else modify( t[lst].rson, t[now].rson, mid + 1, r, pos );
pushup( now );
}
node query( int now, int l, int r, int L, int R ) {
if( L <= l and r <= R ) return t[now];
int mid = ( l + r ) >> 1;
if( R <= mid ) return query( t[now].lson, l, mid, L, R );
else if( mid < L ) return query( t[now].rson, mid + 1, r, L, R );
else {
node lson = query( t[now].lson, l, mid, L, R );
node rson = query( t[now].rson, mid + 1, r, L, R );
int sum = lson.sum + rson.sum;
int lsum = max( lson.lsum, lson.sum + rson.lsum );
int rsum = max( rson.rsum, rson.sum + lson.rsum );
return { sum, lsum, rsum };
}
}
bool check( int x ) {
int ans1 = 0, ans2 = 0, ans3 = 0;
if( opt[2] + 1 <= opt[3] - 1 )
ans1 = query( root[x], 1, n, opt[2] + 1, opt[3] - 1 ).sum;
ans2 = query( root[x], 1, n, opt[1], opt[2] ).rsum;
ans3 = query( root[x], 1, n, opt[3], opt[4] ).lsum;
return ans1 + ans2 + ans3 >= 0;
}
signed main() {
scanf( "%lld", &n );
for( int i = 1;i <= n;i ++ ) {
scanf( "%lld", &a[i].val );
a[i].id = i;
}
build( root[1], 1, n );
sort( a + 1, a + n + 1, []( array x, array y ) { return x.val < y.val; } );
for( int i = 1;i < n;i ++ )
modify( root[i], root[i + 1], 1, n, a[i].id );
scanf( "%lld", &m );
int ans = 0;
while( m -- ) {
for( int i = 1;i <= 4;i ++ ) {
scanf( "%lld", &opt[i] );
opt[i] = ( opt[i] + ans ) % n + 1;
}
sort( opt + 1, opt + 5 );
int l = 1, r = n;
while( l <= r ) {
int mid = ( l + r ) >> 1;
if( check( mid ) ) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf( "%lld\n", ans = a[ans].val );
}
return 0;
}