[链分治][FWT][树链剖分] BZOJ 4911: [Sdoi2017]切树游戏
来源:互联网 发布:python获取svn版本号 编辑:程序博客网 时间:2024/06/06 17:15
Solution
DP是一个异或卷积的形式,可以FWT把
链分治参考immortalCO的博客。
最后还是有些地方
#include <bits/stdc++.h>using namespace std;const int N = 60303;const int M = 130;const int MOD = 10007;const int INV2 = (MOD + 1) >> 1;inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++;}template<typename T>inline void read(T &x) { static char c; x = 0; int sgn = 0; for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1; for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; if (sgn) x = -x;}inline void reado(char &c) { for (c = get(); c != 'Q' && c != 'C'; c = get());}struct edge { int to, next; edge(int t = 0, int n = 0):to(t), next(n) {}};edge G[N << 1];int head[N];int Gcnt, Tcnt, n, m, q, x, y, lim, tnt;int top[N], size[N], son[N], fa[N], dep[N];int inv[N], pos[N], tps[N], w[N];vector<int> s[N];struct Int { int d, c; Int(void) {} Int(int x) { x %= MOD; if (x) d = x, c = 0; else d = 1, c = 1; } inline Int &operator *=(int x) { x %= MOD; if (x == 0) ++c; else d = d * x % MOD; return *this; } inline Int &operator /=(int x) { x %= MOD; if (x == 0) --c; else d = d * inv[x] % MOD; return *this; } inline int val(void) { return c ? 0 : d; }};int num[M][M];Int lt[N][M];int rt[N], ans[N], res[N];int sum[N * 3][M], lval[N * 3][M], rval[N * 3][M], val[N * 3][M];int ls[N * 3], rs[N * 3], par[N * 3];char opt;inline void Add(int &x, int a) { x = (x + a) % MOD;}inline void AddEdge(int from, int to) { G[++Gcnt] = edge(from, head[to]); head[to] = Gcnt; G[++Gcnt] = edge(to, head[from]); head[from] = Gcnt;}inline void dfs1(int u) { int to; size[u] = 1; for (int i = head[u]; i; i = G[i].next) { to = G[i].to; if (to == fa[u]) continue; fa[to] = u; dep[to] = dep[u] + 1; dfs1(to); size[u] += size[to]; if (size[to] > size[son[u]]) son[u] = to; }}inline void dfs2(int u, int t) { top[u] = t; s[t].push_back(u); if (son[u]) dfs2(son[u], t); for (int i = head[u]; i; i = G[i].next) if (G[i].to != fa[u] && G[i].to != son[u]) dfs2(G[i].to, G[i].to);}inline void FWT(int* a, int n, int f) { static int x, y; for (int i = 1; i < n; i <<= 1) for (int j = 0; j < n; j += (i << 1)) for (int k = 0; k < i; k++) { x = a[j + k]; y = a[j + k + i]; a[j + k] = (x + y) % MOD; a[j + k + i] = (x - y + MOD) % MOD; if (f == -1) { a[j + k] = a[j + k] * INV2 % MOD; a[j + k + i] = a[j + k + i] * INV2 % MOD; } }}inline void Prep(int m) { inv[1] = 1; for (int i = 2; i < MOD; i++) inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD; for (int i = 0; i < m; i++) { num[i][i] = 1; FWT(num[i], m, 1); }}inline void PushUp(int o) { int L = ls[o], R = rs[o]; for (int i = 0; i < lim; i++) { val[o][i] = (val[L][i] + val[R][i] + rval[L][i] * lval[R][i]) % MOD; lval[o][i] = (lval[L][i] + lval[R][i] * sum[L][i]) % MOD; rval[o][i] = (rval[R][i] + rval[L][i] * sum[R][i]) % MOD; sum[o][i] = sum[L][i] * sum[R][i] % MOD; }}inline void Build(int &o, int l, int r, int t) { o = ++Tcnt; if (l == r) { for (int i = 0; i < lim; i++) sum[o][i] = lval[o][i] = rval[o][i] = val[o][i] = lt[s[t][l - 1]][i].val(); pos[s[t][l - 1]] = o; return; } int mid = (l + r) >> 1; Build(ls[o], l, mid, t); Build(rs[o], mid + 1, r, t); PushUp(o); par[ls[o]] = par[rs[o]] = o;}inline void Modify(int u) { int t = top[u]; if (fa[t]) for (int i = 0; i < lim; i++) lt[fa[t]][i] /= (lval[rt[t]][i] + num[0][i]) % MOD; for (int i = 0; i < lim; i++) Add(ans[i], MOD - val[rt[t]][i]); int o = pos[u]; for (int i = 0; i < lim; i++) sum[o][i] = lval[o][i] = rval[o][i] = val[o][i] = lt[u][i].val(); o = par[o]; while (o) { PushUp(o); o = par[o]; } if (fa[t]) for (int i = 0; i < lim; i++) lt[fa[t]][i] *= (lval[rt[t]][i] + num[0][i]) % MOD; for (int i = 0; i < lim; i++) Add(ans[i], val[rt[t]][i]);}inline bool cmp(int x, int y) { return dep[x] > dep[y];}int main(void) { freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); read(n); read(m); for (lim = 1; lim < m; lim <<= 1); Prep(lim); for (int i = 1; i <= n; i++) { read(w[i]); for (int j = 0; j < lim; j++) lt[i][j] = Int(num[w[i]][j]); } for (int i = 1; i < n; i++) { read(x); read(y); AddEdge(x, y); } dfs1(1); dfs2(1, 1); for (int i = 1; i <= n; i++) if (top[i] == i) tps[++tnt] = i; sort(tps + 1, tps + tnt + 1, cmp); for (int i = 1; i <= tnt; i++) { int x = tps[i]; Build(rt[x], 1, s[x].size(), x); if (fa[x]) for (int j = 0; j < lim; j++) lt[fa[x]][j] *= (lval[rt[x]][j] + num[0][j]) % MOD; for (int j = 0; j < lim; j++) Add(ans[j], val[rt[x]][j]); } read(q); while (q--) { reado(opt); if (opt == 'C') { read(x); read(y); for (int i = 0; i < lim; i++) lt[x][i] /= num[w[x]][i]; w[x] = y; for (int i = 0; i < lim; i++) lt[x][i] *= num[w[x]][i]; while (x) { Modify(x); x = fa[top[x]]; } } else { read(x); for (int i = 0; i < lim; i++) res[i] = ans[i]; FWT(res, lim, -1); printf("%d\n", res[x]); } } return 0;}
阅读全文
1 0
- [链分治][FWT][树链剖分] BZOJ 4911: [Sdoi2017]切树游戏
- [链分治 重链剖分 FWT] BZOJ 4911 [Sdoi2017]切树游戏
- [FWT && 链分治] BZOJ4911.[Sdoi2017]切树游戏
- [BZOJ4911][SDOI2017]切树游戏-链分治-快速沃尔什变换
- [KMP 高斯消元] BZOJ 4820: [Sdoi2017]硬币游戏
- bzoj 4817: [Sdoi2017]树点涂色
- [LCT] BZOJ 4817 [Sdoi2017]树点涂色
- [线段树] BZOJ 4821 [Sdoi2017]相关分析
- [BZOJ]4821: [Sdoi2017]相关分析 线段树
- bzoj 4821: [Sdoi2017]相关分析 线段树
- [高斯消元 概率 KMP] BZOJ 4820 [Sdoi2017]硬币游戏
- BZOJ 3924 Zjoi2015 幻想乡战略游戏 动态树分治
- bzoj 3924: [Zjoi2015]幻想乡战略游戏 动态树分治
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏 动态树分治
- bzoj 4817: [Sdoi2017]树点涂色 link cut tree+线段树+树链剖分
- BZOJ 3697 树分治
- 【SDOI2017】硬币游戏
- 4820: [Sdoi2017]硬币游戏
- Intellij导入插件工程,不能运行(需要EditConfiguration)
- Sublime Text Snippets(代码片段)功能
- 大型网站电商网站架构案例和技术架构的示例
- 易天强势推出10G SFP+电口模块
- 手机端H5获取当前城市的方法
- [链分治][FWT][树链剖分] BZOJ 4911: [Sdoi2017]切树游戏
- 八大排序算法
- 谈谈RGB、YUY2、YUYV、YVYU、UYVY、AYUV
- 面试技巧
- 稳定排序和不稳定排序
- Slim研读笔记六之应用主体(中)
- spring boot 学习笔记
- ganymed操作shell
- git初步使用笔记