首页 > 其他分享 >P5298 [PKUWC2018]Minimax

P5298 [PKUWC2018]Minimax

时间:2022-12-24 09:34:44浏览次数:49  
标签:lc int Minimax P5298 rc mul sum PKUWC2018 mod

题解

\(f_{u,k}\) 节点 \(u\) 是第 \(k\) 小的点的概率。

\(deg = 2\) 的情况:

\[f_{u,k}=(1-p_u)\left(f_{lc,k}\sum_{k'>k}f_{rc,k'}+f_{rc,k}\sum_{k'>k}f_{lc,k'}+f_{lc,k}f_{rc,k}\right) +p_u\left(f_{lc,k}\sum_{k'<k}f_{rc,k'}+f_{rc,k}\sum_{k'<k}f_{lc,k'}+f_{lc,k}f_{rc,k}\right) \]

因为题目保证点权互不相同,所以

\[f_{u,k}=(1-p_u)\left(f_{lc,k}\sum_{k'>k}f_{rc,k'}+f_{rc,k}\sum_{k'>k}f_{lc,k'}\right) +p_u\left(f_{lc,k}\sum_{k'<k}f_{rc,k'}+f_{rc,k}\sum_{k'<k}f_{lc,k'}\right) \]

\[f_{u,k}=f_{lc,k}\left((1-p_u)\sum_{k'>k}f_{rc,k'}+p_u\sum_{k'<k}f_{rc,k'}\right)+f_{rc,k}\left((1-p_{u})\sum_{k'>k}f_{lc,k'}+p_u\sum_{k'<k}f_{lc,k'}\right) \]

可以考虑线段树合并。

当合并到一个节点为空时,不妨设 \(rc\) 的线段树为空。

设当前线段树区间为 \([l,r]\) 可以发现合并后的值只与 \(lc\) 这棵线段树的值和 \(rc\) 这棵线段树 \([1,l-1]\) 的和,\([r+1,m]\) 的和有关。

这两个值可以在向下递归的时候算出来。

\(lc\) 为空时同理。

总结

本题暴力dp的部分比较好想,但线段树合并较难想到,需要从线段树合并的条件出发思考本题。

线段树合并时更新信息有两个条件:

  1. 有一棵线段树为空。
  2. 节点为叶子节点。

回到本题,我们可以发现dp的式子在这两个条件下都较好维护,因此本题可以使用线段树合并。

进一步思考,我们还可以发现,“每个结点的权值互不相同”这个条件是没有用的,就算权值相同,也可以线段树合并。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int maxn = 3e5 + 5, mod = 998244353;
int n, ch[maxn][2], p[maxn], w[maxn], deg[maxn], a[maxn], m;
#define lc(x) (t[x].lc)
#define rc(x) (t[x].rc)
int root[maxn], cnt;
struct SGT {
	int lc, rc, sum, mul;
	SGT() { lc = sum = 0; mul = 1; }
} t[maxn * 32];
void push_up(int x) {
	t[x].sum = (t[lc(x)].sum + t[rc(x)].sum) % mod;
}
void push_mul(int x, int v) {
	t[x].mul = 1ll * t[x].mul * v % mod;
	t[x].sum = 1ll * t[x].sum * v % mod;
}
void push_down(int x) {
	if(t[x].mul != 1) {
		if(lc(x)) push_mul(lc(x), t[x].mul);
		if(rc(x)) push_mul(rc(x), t[x].mul);
		t[x].mul = 1;
	}
}
void modify(int &x, int l, int r, int p, int v) {
	if(!x) x = ++cnt, t[x].mul = 1;
	if(l == r) {
		t[x].sum = v;
		t[x].mul = 1;
		return;
	}
	int mid = (l + r) >> 1;
	if(mid >= p) modify(lc(x), l, mid, p, v);
	else modify(rc(x), mid + 1, r, p, v);
	push_up(x);
}
int merge(int x, int y, int l, int r, int u, int sumxl, int sumxr, int sumyl, int sumyr) {
	if(!x && !y) return 0;
	if(!y) {
		int v = (1ll * (1 + mod - p[u]) * sumyr % mod + 1ll * p[u] * sumyl % mod) % mod;
		push_mul(x, v);
		return x; 
	}
	if(!x) {
		int v = (1ll * (1 + mod - p[u]) * sumxr % mod + 1ll * p[u] * sumxl % mod) % mod;
		push_mul(y, v);
		return y;
	}
	push_down(x); push_down(y);
	int mid = (l + r) >> 1, s1 = t[lc(x)].sum, s2 = t[rc(x)].sum, s3 = t[lc(y)].sum, s4 = t[rc(y)].sum;
	lc(x) = merge(lc(x), lc(y), l, mid, u, sumxl, (sumxr + s2) % mod, sumyl, (sumyr + s4) % mod);
	rc(x) = merge(rc(x), rc(y), mid + 1, r, u, (sumxl + s1) % mod, sumxr, (sumyl + s3) % mod, sumyr);
	push_up(x);
	return x;
}
int query(int x, int l, int r, int p) {
	if(!x) return 0;
	if(l == r) return t[x].sum;
	push_down(x); int mid = (l + r) >> 1;
	if(mid >= p) return query(lc(x), l, mid, p);
	else return query(rc(x), mid + 1, r, p);
}
#undef lc
#undef rc
int ksm(int x, int y) {
	int res = 1;
	while(y) {
		if(y & 1) res = 1ll * res * x % mod;
		x = 1ll * x * x % mod, y >>= 1;
	}
	return res;
}
void dfs(int u) {
	if(deg[u] == 0) {
		int k = lower_bound(a + 1, a + 1 + m, w[u]) - a;
		modify(root[u], 1, m, k, 1);
		return;
	}
	if(deg[u] == 1) {
		if(ch[u][0]) dfs(ch[u][0]), root[u] = root[ch[u][0]];
		if(ch[u][1]) dfs(ch[u][1]), root[u] = root[ch[u][1]];
		return;
	}
	dfs(ch[u][0]); dfs(ch[u][1]);
	root[u] = merge(root[ch[u][0]], root[ch[u][1]], 1, m, u, 0, 0, 0, 0);
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n;
	for(int i = 1, fa; i <= n; i++) {
		cin >> fa;
		if(!ch[fa][0]) ch[fa][0] = i;
		else ch[fa][1] = i;
		deg[fa]++;
	}
	for(int i = 1, x, fm = ksm(10000, mod - 2); i <= n; i++) {
		cin >> x;
		if(deg[i] == 0) w[i] = x, a[++m] = x;
		else p[i] = 1ll * x * fm % mod;
	}
	sort(a + 1, a + 1 + m);
	dfs(1);
	int ans = 0;
	for(int i = 1; i <= m; i++) {
		int pp = query(1, 1, m, i);
		ans = (ans + 1ll * i * a[i] % mod * pp % mod * pp % mod) % mod;
	}
	cout << ans << '\n';
	return 0;
}

标签:lc,int,Minimax,P5298,rc,mul,sum,PKUWC2018,mod
From: https://www.cnblogs.com/yanchengzhi/p/17002029.html

相关文章

  • 最大面积最小的三角剖分 Minimax Triangulation
    #include<iostream>#include<algorithm>#include<cmath>#include<vector>usingnamespacestd;#definemistake(P)(fabs(P)<eps?0:(P<0?-1:1))......
  • 博弈论与强化学习 一 Minimax Q, Nash Q ,FFQ
    博弈解与强化学习二基础算法2.1引言一个随机博弈可以看成是一个多智能体强化学习过程,但其实这两个概念不能完全等价,随机博弈中假定每个状态的奖励矩阵是已知的,不需要......
  • P5643 [PKUWC2018]随机游走
    求出所有\(E_{\min}(S)\),然后FWT求\(E_{\max}(S)\)枚举集合\(S\),记\(f_{u}\)表示从终点\(u\)走到\(S\)中节点的期望步数。对于不属于\(S\)的点\(u\),有:......