int n, b, ans, u, v; int p[MAXN], pro[MAXN], belong[MAXN];
template <classT> voidread(T &x, Tf = 1, charch = getchar()) { x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
structedge { int to, nxt; } e[MAXN << 1];
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
stack<int> s; voiddfs(int now, int fa){ int tmp = s.size(); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != fa) { dfs(to, now); if (s.size() - tmp >= b) { pro[++ans] = now; while (s.size() > tmp) { int cur = s.top(); s.pop(); belong[cur] = ans; } } } } s.push(now); }
intmain(){ read(n), read(b); fill(p, p + n + 1, -1); for (int i = 1; i <= n - 1; i++) { read(u), read(v); addEdge(u, v), addEdge(v, u); } dfs(1, 1); if (!ans) pro[++ans] = 1; while (!s.empty()) { int tmp = s.top(); s.pop(); belong[tmp] = ans; } printf("%d\n", ans); for (int i = 1; i <= n; i++) printf("%d ", belong[i]); printf("\n"); for (int i = 1; i <= ans; i++) printf("%d ", pro[i]); return0; }
int n, m, B, cntB, tot; int val[MAXN], p[MAXN], belong[MAXN], ans[MAXN], cntC[MAXN]; int hson[MAXN], sz[MAXN], dep[MAXN], f[MAXN], top[MAXN]; bool vis[MAXN]; vector<int> v;
template <classT> voidread(T &x, Tf = 1, charch = getchar()) { x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
structEdge { int to, nxt; } e[MAXN * 2];
structQuery { int x, y, id; friendbooloperator<(const Query &a, const Query &b) { if (belong[a.x] == belong[b.x]) { if (belong[a.x] & 1) return belong[a.y] < belong[b.y]; return belong[a.y] > belong[b.y]; } return belong[a.x] < belong[b.x]; } } q[MAXN * 3];
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
stack<int> s; voiddfs(int now, int fa){ sz[now] = 1, dep[now] = dep[fa] + 1, f[now] = fa; int tmp = s.size(); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != fa) { dfs(to, now); sz[now] += sz[to]; if (!hson[now] || sz[to] > sz[hson[now]]) hson[now] = to; if (s.size() - tmp >= B) { cntB++; while (s.size() > tmp) { int cur = s.top(); s.pop(); belong[cur] = cntB; } } } } s.push(now); }
voiddfs2(int now, int tp){ top[now] = tp; if (!hson[now]) return; dfs2(hson[now], tp); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != f[now] && to != hson[now]) dfs2(to, to); } }
intlca(int u, int v){ if (dep[top[u]] < dep[top[v]]) swap(u, v); while (top[u] != top[v]) { u = f[top[u]]; if (dep[top[u]] < dep[top[v]]) swap(u, v); } if (dep[u] < dep[v]) swap(u, v); return v; }
voidgetBlock(){ B = sqrt(n); dfs(1, 1); dfs2(1, 1); if (!cntB) ++cntB; while (!s.empty()) { int tmp = s.top(); s.pop(); belong[tmp] = cntB; } }
voiddiscretize(){ sort(v.begin(), v.end()); for (int i = 1; i <= n; i++) val[i] = lower_bound(v.begin(), v.end(), val[i]) - v.begin() + 1; }
voidmodify(int now){ if (!vis[now]) { ++cntC[val[now]]; if (cntC[val[now]] == 1) tot++; } else { --cntC[val[now]]; if (cntC[val[now]] == 0) tot--; } vis[now] ^= 1; }
voidupdate(int u, int v){ if (dep[u] < dep[v]) swap(u, v); while (dep[u] > dep[v]) modify(u), u = f[u]; while (u != v) modify(u), modify(v), u = f[u], v = f[v]; }
intmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(val[i]), v.push_back(val[i]); discretize(); fill(p + 1, p + n + 1, -1); int x(0), y(0); for (int i = 1; i <= n - 1; i++) { read(x), read(y); addEdge(x, y), addEdge(y, x); } getBlock(); for (int i = 1; i <= m; i++) { read(q[i].x), read(q[i].y); q[i].id = i; } sort(q + 1, q + m + 1); x = 1, y = 1; modify(1); for (int i = 1; i <= m; i++) { int lca1 = lca(x, y), lca2 = lca(q[i].x, q[i].y); update(x, q[i].x), x = q[i].x; update(y, q[i].y), y = q[i].y; modify(lca1), modify(lca2); ans[q[i].id] = tot; } for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return0; }
Solution2
考虑把树上的问题转化到序列上。
这里引入欧拉序,它的思想是:当访问到点i 时,加入序列,记录时间戳 in[i],然后访问 i 的子树,当访问完时,再把 i 加入序列,并记录时间戳 out[i]。如果将一条链映射到序列中的一段区间,那么这个区间中出现两次的节点一定不属于这条链(两端点的 lca)除外, 这样只需要统计出现一次的节点即可。
int n, m, B, tot; int val[MAXN], p[MAXN], in[MAXN], out[MAXN], from[MAXN * 2]; int belong[MAXN * 2], ans[MAXN], cntC[MAXN]; int hson[MAXN], sz[MAXN], dep[MAXN], f[MAXN], top[MAXN]; bool vis[MAXN]; vector<int> v;
template <classT> voidread(T &x, Tf = 1, charch = getchar()) { x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
voiddfs(int now, int fa){ staticint tim = 1; in[now] = tim, from[tim++] = now; sz[now] = 1, dep[now] = dep[fa] + 1, f[now] = fa; for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != fa) { dfs(to, now); sz[now] += sz[to]; if (!hson[now] || sz[to] > sz[hson[now]]) hson[now] = to; } } out[now] = tim, from[tim++] = now; }
voiddfs2(int now, int tp){ top[now] = tp; if (!hson[now]) return; dfs2(hson[now], tp); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != f[now] && to != hson[now]) dfs2(to, to); } }
intlca(int u, int v){ if (dep[top[u]] < dep[top[v]]) swap(u, v); while (top[u] != top[v]) { u = f[top[u]]; if (dep[top[u]] < dep[top[v]]) swap(u, v); } if (dep[u] < dep[v]) swap(u, v); return v; }
voiddiscretize(){ sort(v.begin(), v.end()); for (int i = 1; i <= n; i++) val[i] = lower_bound(v.begin(), v.end(), val[i]) - v.begin() + 1; }
voidmodify(int now){ if (!vis[now]) { ++cntC[val[now]]; if (cntC[val[now]] == 1) tot++; } else { --cntC[val[now]]; if (cntC[val[now]] == 0) tot--; } vis[now] ^= 1; }
intmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(val[i]), v.push_back(val[i]); discretize(); fill(p + 1, p + n + 1, -1); int x(0), y(0); for (int i = 1; i <= n - 1; i++) { read(x), read(y); addEdge(x, y), addEdge(y, x); } B = max(1, 2 * n / (int)sqrt(m)); dfs(1, 1), dfs2(1, 1); for (int i = 1; i <= m; i++) { read(x), read(y); if (in[x] > in[y]) swap(x, y); q[i].lca = lca(x, y); if (q[i].lca == x) { q[i].l = in[x]; q[i].r = in[y]; q[i].lca = 0; } else { q[i].l = out[x]; q[i].r = in[y]; } q[i].id = i; } for (int i = 1; i <= 2 * n; i++) belong[i] = (i - 1) / B + 1; sort(q + 1, q + m + 1); x = 1, y = 0; for (int i = 1; i <= m; i++) { while (x < q[i].l) modify(from[x++]); while (x > q[i].l) modify(from[--x]); while (y > q[i].r) modify(from[y--]); while (y < q[i].r) modify(from[++y]); if (q[i].lca) modify(q[i].lca); ans[q[i].id] = tot; if (q[i].lca) modify(q[i].lca); } for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return0; }
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
voiddfs(int now, int fa){ staticint tim = 1; in[now] = tim, from[tim++] = now; sz[now] = 1, dep[now] = dep[fa] + 1, f[now] = fa; for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != fa) { dfs(to, now); sz[now] += sz[to]; if (!hson[now] || sz[to] > sz[hson[now]]) hson[now] = to; } } out[now] = tim, from[tim++] = now; }
voiddfs2(int now, int tp){ top[now] = tp; if (!hson[now]) return; dfs2(hson[now], tp); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != f[now] && to != hson[now]) dfs2(to, to); } }
intlca(int u, int v){ if (dep[top[u]] < dep[top[v]]) swap(u, v); while (top[u] != top[v]) { u = f[top[u]]; if (dep[top[u]] < dep[top[v]]) swap(u, v); } if (dep[u] < dep[v]) swap(u, v); return v; }
voidmodify(int now){ if (!vis[now]) { ++cntC[C[now]]; tot += 1ll * W[cntC[C[now]]] * V[C[now]]; } else { tot -= 1ll * W[cntC[C[now]]] * V[C[now]]; --cntC[C[now]]; } vis[now] ^= 1; }
constint MAXN = 1e5 + 5; int n, m, Q, B, type, cntQ, cntR, cntB; int C[MAXN], V[MAXN], W[MAXN]; ll tot, ans[MAXN]; int p[MAXN]; int belong[MAXN], cntC[MAXN]; int hson[MAXN], sz[MAXN], dep[MAXN], f[MAXN], top[MAXN]; bool vis[MAXN];
template <classT> voidread(T &x, Tf = 1, charch = getchar()) { x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
structEdge { int to, nxt; } e[MAXN * 2];
structQuery { int x, y, id, t; friendbooloperator<(const Query &a, const Query &b) { if (belong[a.x] == belong[b.x]) { if (belong[a.y] == belong[b.y]) return a.t < b.t; if (belong[a.x] & 1) return belong[a.y] < belong[b.y]; return belong[a.y] > belong[b.y]; } return belong[a.x] < belong[b.x]; } } q[MAXN];
structReplace { int id, type; } r[MAXN];
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
stack<int> s; voiddfs(int now, int fa){ sz[now] = 1, dep[now] = dep[fa] + 1, f[now] = fa; int tmp = s.size(); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != fa) { dfs(to, now); sz[now] += sz[to]; if (!hson[now] || sz[to] > sz[hson[now]]) hson[now] = to; if (s.size() - tmp >= B) { cntB++; while (s.size() > tmp) { int cur = s.top(); s.pop(); belong[cur] = cntB; } } } } s.push(now); }
voiddfs2(int now, int tp){ top[now] = tp; if (!hson[now]) return; dfs2(hson[now], tp); for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (to != f[now] && to != hson[now]) dfs2(to, to); } }
intlca(int u, int v){ if (dep[top[u]] < dep[top[v]]) swap(u, v); while (top[u] != top[v]) { u = f[top[u]]; if (dep[top[u]] < dep[top[v]]) swap(u, v); } if (dep[u] < dep[v]) swap(u, v); return v; }
voidgetBlock(){ B = sqrt(n); dfs(1, 1); dfs2(1, 1); if (!cntB) ++cntB; while (!s.empty()) { int tmp = s.top(); s.pop(); belong[tmp] = cntB; } }
voidmodify(int now){ if (!vis[now]) { ++cntC[C[now]]; tot += 1ll * W[cntC[C[now]]] * V[C[now]]; } else { tot -= 1ll * W[cntC[C[now]]] * V[C[now]]; --cntC[C[now]]; } vis[now] ^= 1; }
voidupdate(int u, int v){ if (dep[u] < dep[v]) swap(u, v); while (dep[u] > dep[v]) modify(u), u = f[u]; while (u != v) modify(u), modify(v), u = f[u], v = f[v]; }