http://www.javashuo.com/article/p-tldaqyfl-bo.html
https://www.cnblogs.com/candy99/p/dsuontree.html
http://www.javashuo.com/article/p-rqtzrwgk-n.htmlhtml
樹上啓發式合併
用到了heavy−light decomposition樹鏈剖分
把輕邊子樹的信息合併到重鏈上的點裏
由於每次都是先dfs輕兒子再dfs重兒子,只有重兒子子樹的貢獻保留,因此能夠保證dfs到每顆子樹時當前全局維護的信息不會有別的子樹裏的,和莫隊很像node
1.遍歷輕兒子
2.遍歷重兒子(保留數據)
3.計算全部輕兒子爲根的子樹
4.若是當前點是輕兒子,清空影響c++
樹鏈剖分後每一個點到根的路徑上有\(logn\)條輕邊和\(logn\)條重鏈算法
每一個點碰見輕邊時合併一次,因此至多\(logn\)次spa
總複雜度\(O(nlogn)\)code
http://codeforces.com/contest/600/problem/E
題意:詢問每顆子樹中出現次數最多的顏色們編號和htm
板子題blog
Codeget
#include<bits/stdc++.h> #define LL long long #define RG register using namespace std; template<class T> inline void read(T &x) { x = 0; RG char c = getchar(); bool f = 0; while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1; while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar(); x = f ? -x : x; return ; } template<class T> inline void write(T x) { if (!x) {putchar(48);return ;} if (x < 0) x = -x, putchar('-'); int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10; for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ; } const int N = 1e5+10; int c[N], n; struct node { int to, nxt; }g[N<<1]; int last[N], gl; void add(int x, int y) { g[++gl] = (node) {y, last[x]}; last[x] = gl; } int son[N], siz[N]; void dfs1(int u, int f) { siz[u] = 1; for (int i = last[u]; i; i = g[i].nxt) { int v = g[i].to; if (v == f) continue; dfs1(v, u); siz[u] += siz[v]; if (siz[son[u]] < siz[v]) son[u] = v; } return ; } int num[N], top; LL sum[N], ans[N]; bool vis[N]; void calc(int u, int fa, int k) { sum[num[c[u]]] -= c[u]; num[c[u]] += k; sum[num[c[u]]] += c[u]; if (sum[top + 1]) top++; else if (!sum[top]) top--; for (int i = last[u]; i; i = g[i].nxt) { int v = g[i].to; if (v == fa || vis[v]) continue; calc(v, u, k); } return ; } void dfs(int u, int fa, int op) { for (int i = last[u]; i; i = g[i].nxt) if (g[i].to != fa && g[i].to != son[u]) dfs(g[i].to, u, 0); if (son[u]) dfs(son[u], u, 1), vis[son[u]] = 1; calc(u, fa, 1); vis[son[u]] = 0; ans[u] = sum[top]; if (!op) calc(u, fa, -1); return ; } int main() { read(n); for (int i = 1; i <= n; i++) read(c[i]); for (int i = 1; i < n; i++) { int x, y; read(x), read(y); add(x, y), add(y, x); } dfs1(1, 0); dfs(1, 0, 1); for (int i = 1; i <= n; i++) printf("%I64d ", ans[i]); return 0; }
http://codeforces.com/problemset/problem/570/D
https://www.luogu.org/problemnew/show/CF570Drequests
構成迴文串,奇數個的字母至多一個
用二進制狀壓判斷便可
\(sum[x]\)表示深度爲\(x\)構成的狀態
#include<bits/stdc++.h> #define LL long long #define RG register using namespace std; template<class T> inline void read(T &x) { x = 0; RG char c = getchar(); bool f = 0; while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1; while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar(); x = f ? -x : x; return ; } template<class T> inline void write(T x) { if (!x) {putchar(48);return ;} if (x < 0) x = -x, putchar('-'); int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10; for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ; } const int N = 500010; struct node { int to, nxt; }g[N<<1], q[N]; int last[N], gl; int n, m; void add(int x, int y) { g[++gl] = (node) {y, last[x]}; last[x] = gl; g[++gl] = (node) {x, last[y]}; last[y] = gl; } char s[N]; int siz[N], son[N], val[N], dep[N], sum[N]; bool vis[N]; void dfs1(int u, int fa) { siz[u] = 1; for (int i = last[u]; i; i = g[i].nxt) { int v = g[i].to; if (v == fa) continue; dep[v] = dep[u] + 1; dfs1(v, u); siz[u] += siz[v]; if (siz[son[u]] < siz[v]) son[u] = v; } } void calc(int u, int fa) { sum[dep[u]] ^= val[u]; for (int i = last[u]; i; i = g[i].nxt) { int v = g[i].to; if (v == fa || vis[v]) continue; calc(v, u); } return ; } struct Node { int h, nxt; }a[N]; bool ans[N]; int S[N]; bool cal(int x) { int tmp = 0; while (x) { tmp++; x -= (x & (-x)); } return tmp <= 1; } void dfs(int u, int fa, int op) { for (int i = last[u]; i; i = g[i].nxt) { int v = g[i].to; if (v == fa || son[u] == v) continue; dfs(v, u, 0); } if (son[u]) dfs(son[u], u, 1), vis[son[u]] = 1; calc(u, fa); vis[son[u]] = 0; for (int i = S[u]; i; i = a[i].nxt) ans[i] = cal(sum[a[i].h]); if (!op) calc(u, fa); return ; } int main() { read(n), read(m); for (int i = 2; i <= n; i++) { int x; read(x); add(x, i); } scanf("%s", s+1); for (int i = 1; i <= n; i++) val[i] = 1<<(s[i]-'a'); dep[1] = 1; dfs1(1, 0); for (int i = 1; i <= m; i++) { int h, v; read(v), read(h); a[i].nxt = S[v]; S[v] = i; a[i].h = h; } dfs(1, 0, 1); for (int i = 1; i <= m; i++) puts(ans[i] ? "Yes" : "No"); return 0; }