【LG2839】[国家集训队]middle

【LG2839】[国家集训队]middle

题面

洛谷

题解

按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\)

若一个区间和大于等于\(0\),则答案可以更大,反之亦然。

对于这个题,我们只要维护出\([b+1,c-1]\)之间二分答案后的和,\([a,b]\)的最大右段和,\([c,d]\)的最大左段和,判断这三项加起来是否大于零即可。

我们维护这三项和的话,按照权值为前缀,建主席树就行了。

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
using namespace std;
inline int gi() {
    register int data = 0, w = 1; 
    register char ch = 0; 
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
} 
const int MAX_N = 2e4 + 5; 
struct Info { 
	int lmax, rmax, sum;
	Info () {lmax = rmax = -1, sum = 0; } 
	Info (int lmax, int rmax, int sum) : lmax(lmax), rmax(rmax), sum(sum) { } 
} ; 
Info operator + (Info l, Info r) { 
	Info res; 
	res.lmax = max(l.lmax, l.sum + r.lmax); 
	res.rmax = max(r.rmax, r.sum + l.rmax);
	res.sum = l.sum + r.sum; 
	return res; 
} 
struct Node { int ls, rs; Info v; } t[MAX_N * 20]; 
int rt[MAX_N], tot = 0; 
void build(int &o, int l, int r) { 
	o = ++tot; 
	t[o].v = (Info){r - l + 1, r - l + 1, r - l + 1}; 
	if (l == r) return ;
	int mid = (l + r) >> 1; 
	build(t[o].ls, l, mid);
	build(t[o].rs, mid + 1, r); 
} 
void insert(int &o, int p, int l, int r, int pos) { 
	o = ++tot, t[o] = t[p]; 
	if (l == r) return (void)(t[o].v = (Info){-1, -1, -1}); 
	int mid = (l + r) >> 1; 
	if (pos <= mid) insert(t[o].ls, t[p].ls, l, mid, pos); 
	else insert(t[o].rs, t[p].rs, mid + 1, r, pos); 
	t[o].v = t[t[o].ls].v + t[t[o].rs].v; 
} 
Info query(int o, int l, int r, int ql, int qr) { 
	if (ql <= l && r <= qr) return t[o].v; 
	int mid = (l + r) >> 1; Info res; 
	if (ql <= mid) res = res + query(t[o].ls, l, mid, ql, qr);
	if (qr > mid) res = res + query(t[o].rs, mid + 1, r, ql, qr); 
	return res; 
} 
int N, id[MAX_N], a[MAX_N], q[5]; 
bool check(int mid) { 
	int val = 0; 
	if (q[1] + 1 <= q[2] - 1) val += query(rt[mid], 1, N, q[1] + 1, q[2] - 1).sum; 
	val += query(rt[mid], 1, N, q[0], q[1]).rmax; 
	val += query(rt[mid], 1, N, q[2], q[3]).lmax; 
	return val >= 0; 
} 
bool cmp(const int &x, const int &y) { return a[x] < a[y]; } 
int main() { 
#ifndef ONLINE_JUDGE 
	freopen("cpp.in", "r", stdin); 
#endif 
	N = gi(); build(rt[1], 1, N); 
	for (int i = 1; i <= N; i++) a[i] = gi(), id[i] = i; 
	sort(&id[1], &id[N + 1], cmp); 
	for (int i = 2; i <= N; i++) insert(rt[i], rt[i - 1], 1, N, id[i - 1]); 
	for (int Q = gi(), ans = 0; Q--; ) { 
		for (int i = 0; i < 4; i++) q[i] = (gi() + ans) % N + 1;
		sort(&q[0], &q[4]);
		int l = 1, r = N;
		while (l <= r) {
			int mid = (l + r) >> 1; 
			if (check(mid)) ans = a[id[mid]], l = mid + 1;
			else r = mid - 1; 
		} 
		printf("%d\n", ans); 
	} 
    return 0;
}
posted @ 2019-10-17 21:40  heyujun  阅读(157)  评论(0编辑  收藏  举报