文章目录
- 点击查看
- solution
- code
点击查看
solution
简单口胡一下就跑
考虑二分答案ansansans
区间[x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1∈[a,b],x2∈[c,d]
大于等于ansansans的设为111,小于ansansans的设为000
如果和≥0\ge 0≥0表示ansansans还可以更大,否则应该变小
发现无论x1,x2x1,x2x1,x2怎么取,有一段是肯定包含的→[b+1,c−1]\rightarrow[b+1,c-1]→[b+1,c−1]
即,只需要最大化[x1,b],[c,x2][x1,b],[c,x2][x1,b],[c,x2]之间的和,就是一个最大后缀/最大前缀问题
可以利用线段树求解
对于每一个中位数建立一棵线段树
发现空间飞了
主席树硬刚
值域远大于“““定义域”””
离散搞tatata
详情请见下方代码
⇓\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;
}