Loading

AGC028E 做题记录

好厉害!

首先使用贪心策略,从左往右扫,能填 \(0\) 就填 \(0\),问题变为判定性问题。

首先我们先观察性质

  • 性质:\(P\) 中的前缀最大值一定有 \(1\) 的贡献,其他元素的贡献可以为 \(0\),一定条件下可以为 \(1\)

然后就不会了,个人只会 \(O(n^2)\) 的 DP。

考虑猜结论

  • 结论:把 \(P_{i+1 ... n}\) 分配给两个序列,存在一种最优方案,满足其中一个序列中的贡献都是 \(P\) 的前缀最大值。

证明:假设两个序列有两个非前缀最大值的贡献 \(x,y\),那么交换 \(x,y\) 的分配,两个贡献都会去掉。

所以我们只需要分讨一下这个序列是 \(A\) 还是 \(B\),假设为 \(A\)

\(c_A,c_B\) 分别为 \(A,B\)\(P_{1...i}\) 的贡献,那么 \(P_{i+1...n}\) 的分配需要满足 \(A\) 的贡献减去 \(B\) 的贡献等于 \(c_B-c_A\)

\(D = c_A - c_B\)\(S\)\(P_{i+1...n}\) 在原排列的前缀最大值个数,\(T\) 为分配给 \(B\) 的前缀最大值,\(E\) 为剩余可贡献的数量。

那么 \(A\) 的剩余贡献为 \(S-T\)\(B\) 的剩余贡献为 \(T+[0,E]\),关系式为 \((S-T)-(T+E) = D \Leftrightarrow 2T+[0,E] = S-D\)

我们解读一下这个式子,相当于在 \(P_{i+1...n}\) 中选择一个上升子序列,前缀最大值的贡献为 \(2\),其他数贡献为 \(1\),满足总贡献为 \(S-D\),问是否存在这样的方案。

  • trick:注意到如果我们确定了一个方案,贡献为 \(v\),那么 \(v-2\) 也是可行的。

所以我们分奇偶两种,dp 算最大贡献。

使用线段树,时间复杂度 \(O(n\log n)\)

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define fi first
#define se second
#define pir pair <ll, ll>
#define mkp make_pair
#define pb push_back
using namespace std;
const ll maxn = 2e5 + 10, inf = 1e17;
ll n, a[maxn], b[maxn], f[maxn][2], sum[maxn];
struct SGT {
	ll mx[maxn << 2];
	void modify(ll p, ll l, ll r, ll x, ll v) {
		if(l == r) {mx[p] = v; return;}
		ll mid = l + r >> 1;
		if(x <= mid) modify(p << 1, l, mid, x, v);
		else modify(p << 1|1, mid + 1, r, x, v);
		mx[p] = max(mx[p << 1], mx[p << 1|1]);
	}
	ll query(ll p, ll l, ll r, ll ql) {
		if(ql <= l) return mx[p];
		if(r < ql) return -inf;
		ll mid = l + r >> 1;
		return max(query(p << 1, l, mid, ql), query(p << 1|1, mid + 1, r, ql));
	}
} T[2];
ll mx1, mx2, c1, c2, pos[maxn];
bool chk(ll i) {
	ll D = c1 - c2, t = (sum[i + 1] + D + 10000000) & 1;
	if(sum[i + 1] >= D && T[t].query(1, 1, n + 1, mx1) >= sum[i + 1] - D) return 1;
	if(sum[i + 1] >= -D && T[t].query(1, 1, n + 1, mx2) >= sum[i + 1] + D) return 1;
	return 0;
}
int main() {
	scanf("%lld", &n);
	for(ll i = 1, mx = 0; i <= n; i++) {
		scanf("%lld", a + i);
		pos[a[i]] = i;
		if(a[i] > mx) {
			b[i] = 1;
			mx = a[i];
		}
		T[0].modify(1, 1, n + 1, i, -inf);
		T[1].modify(1, 1, n + 1, i, -inf);
	}
	T[1].modify(1, 1, n + 1, n + 1, -inf);
	for(ll i = n; i; i--) {
		sum[i] = sum[i + 1] + b[i];
		f[i][0] = T[b[i] ^ 1].query(1, 1, n + 1, a[i]) + 1 + b[i];
		f[i][1] = T[b[i]].query(1, 1, n + 1, a[i]) + 1 + b[i];
		T[0].modify(1, 1, n + 1, a[i], f[i][0]);
		T[1].modify(1, 1, n + 1, a[i], f[i][1]);
	}
	if(!chk(0)) {puts("-1"); return 0;}
	for(ll i = 1; i <= n; i++) {
		ll tmpmx = mx1, tmpc = c1;
		mx1 = max(mx1, a[i]), c1 += (mx1 == a[i]);
		T[0].modify(1, 1, n + 1, a[i], -inf);
		T[1].modify(1, 1, n + 1, a[i], -inf);
		if(!chk(i)) {
			mx1 = tmpmx, c1 = tmpc;
			mx2 = max(mx2, a[i]), c2 += (mx2 == a[i]);
			putchar('1');
		} else putchar('0');
	}
	return 0;
}
posted @ 2024-05-10 16:24  Lgx_Q  阅读(10)  评论(0编辑  收藏  举报