目录
目录
树
博弈
传送
树
给一棵根为 1 的有根树,点 i 具有一个权值 Ai 。
定义一个点对的值 f(u,v)=max(Au,Av)×|Au−Av| 。
你需要对于每个节点 i ,计算 ansi=∑u∈subtree(i),v∈subtree(i)f(u,v) ,其中 subtree(i) 表示 i 的子树。
请你输出 ⊕(ansi mod 2^64) ,其中 ⊕ 表示 XOR。
满足 n≤5×105,1≤Ai≤106
用到线段树合并+权值线段树
max(Au,Av)*|Au-Av| = max(Au,Av) * max(Au,Av) - max(Au,Av) * min(Au,Av)
=
考虑用线段树维护三个值:区间和、区间平方和、区间个数
右区间一定大于左区间,当我们算两个子树合并的贡献时,用右区间的区间平方数乘上左区间的区间个数可以得到 (u,v都在i子树内,且跨越i相连), 左右区间和相乘可以得到
如果v在u子树里,v子树的答案已经算过了,在算u时直接加上v的答案即可。
关于线段树合并+权值线段树的复杂度:
是权值线段树,总点数和n的规模相差并不大。并且合并时一般不会重复地合并某个线段树,所以我们最终增加的点数大致是nlogn级别的。这样,总的复杂度就是nlogn级别的。(摘自oiwiki)
另外注意的小点:
⊕(ansi mod 2^64) 直接用unsigned long long 自然溢出即可,mod会爆
献上调了两小时的代码一份:
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N = 2e6 + 10;
int a[N];
vector<int> to[N];
int dp[N], rt[N << 3], ls[N << 3], rs[N << 3], sz[N << 3];
int sum[N << 3], sum2[N << 3];void update(int id) {sum2[id] = sum2[ls[id]] + sum2[rs[id]];sum[id] = sum[ls[id]] + sum[rs[id]];sz[id] = sz[ls[id]] + sz[rs[id]];
}
int now ;
int merge(int a, int b, int x, int y) {if (!a)return b;if (!b)return a;if (x == y) {sz[a] += sz[b];sum2[a] += sum2[b];sum[a] += sum[b];return a;}int mid = (x + y) >> 1;if (ls[a] != 0 && rs[b] != 0) {now += sz[ls[a]] * sum2[rs[b]] * 2ll,now -= sum[ls[a]] * sum[rs[b]] * 2ll;}if (ls[b] != 0 && rs[a] != 0) {now+= sz[ls[b]] * sum2[rs[a]] * 2ll, now -= sum[ls[b]] * sum[rs[a]] * 2ll;}ls[a] = merge(ls[a], ls[b], x, mid);rs[a] = merge(rs[a], rs[b], mid + 1, y);update(a);return a;
}int cnt = 0;int add(int &id, int x, int y, int co) {if (!id) id = ++cnt;if (x == y) {sum2[id] += co * co;sum[id] += co;sz[id]++;return id;}int mid = (x + y) >> 1;if (co <= mid) {ls[id] = add(ls[id], x, mid, co);} else {rs[id] = add(rs[id], mid + 1, y, co);}update(id);return id;
}int ans = 0;
void dfs(int x, int f) {int res = 0;add(rt[x], 1, 1000000, a[x]);for (int i = 0; i < to[x].size(); i++) {int v = to[x][i];if (v == f)continue;dfs(v, x);res += dp[v];now = 0;merge(rt[x], rt[v], 1, 1000000);res+=now;}dp[x] = res;ans ^= res;return;
}void solve() {int n;cin >> n;for (int i = 1; i <= n - 1; i++) {int u, v;cin >> u >> v;to[u].push_back(v);to[v].push_back(u);}for (int i = 1; i <= n; i++)cin >> a[i];dfs(1, -1);cout << ans << '\n';
}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);int _ = 1;while (_--) solve();return 0;
}
博弈
小马给出了一个可重小写字符集合 S。
Alice 初始时有空串 A,Bob 初始时有空串 B。
两人轮流等概率取出集合 S 中的一个字符 c,将它拼接到自己的字符串的后面,直至 S 为空,每个字符只能被取一次,Alice 先手。
如果最终 A 的字典序严格大于 B,则 Alice 胜利,求其获胜的概率,答案对 998244353取模。
考虑 为偶数的情况:
i)平局,所有字符都有偶数个:
A先手随便拿一个字符ai,B后手跟着拿ai,A继续拿aj,B跟着拿aj,那么平局的概率p就是
ii)非平局的情况,无非胜或败,败的情况翻转一下就是胜,所以胜局的概率就是
sum为奇数的情况:
i)讨论前sum-1个可以达到平局的情况,在这个情况下由于A先手,所以A必胜
此时所有字符有且只有一个奇数a[idx],我们先将这个奇数拿出一个,然后重复上面的平局过程:
易得
我们可以简化计算,当拿出了奇数中的一个后,a[idx]--,sum--。(具体看代码就懂了)
ii)前sum-1个非平局的情况,无非胜或败,败的情况翻转一下就是胜,此时胜局的概率就是
iii)总的来说,此时胜局的概率就是
#include<bits/stdc++.h>#define int long long
using namespace std;
typedef long long ll;
const int N = 1e7 + 10;
const int mod = 998244353;int a[30], n, f[N];ll poww(ll a, ll b) {ll t = 1;while (b) {if (b & 1)t = t * a % mod;a = a * a % mod;b >>= 1;}return t;}void init() {f[1] = 1;for (int i = 3; i <= N - 5; i += 2) {f[i] = f[i - 2] * i % mod;}}void mul(int &a, int b) {a = ((a % mod * b % mod) + mod) % mod;
}void solve() {cin >> n;int sum = 0, cnt = 0, idx = -1;char c;for (int i = 1; i <= n; i++) {cin >> c >> a[i], sum += a[i];if (a[i] & 1) cnt++, idx = i;}int p = 1;if (sum & 1) {if (cnt != 1) p = 0;else {mul(p, a[idx] * poww(sum, mod - 2) % mod);sum--;mul(p, poww(f[sum - 1], mod - 2));for (int i = 1; i <= n; i++) {if (i == idx) {if (a[i] > 2)mul(p, f[a[i] - 2]);} else {mul(p, f[a[i] - 1]);}}}cout << ((1 + p) % mod * poww(2, mod - 2)) % mod << '\n';} else {if (cnt != 0)p = 0;else {mul(p, poww(f[sum - 1], mod - 2));for (int i = 1; i <= n; i++) {mul(p, f[a[i] - 1]);}}cout << ((1 - p + mod) % mod * poww(2, mod - 2) % mod + mod) % mod;}}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);int _ = 1;init();cin >> _;while (_--) solve();return 0;
}
/*
1
2
a 2
c 2
332748118*/
传送
线段树分治+可撤销并查集
学了之后发现是板子题,贴个链接https://blog.csdn.net/landexiangmz/article/details/140587889?spm=1001.2014.3001.5502