题意:给出一个树,以1号节点为根,然后每次操作给一个节点一个颜色,最后询问所有节点所对应的子树不同颜色的个数。
解法:预处理LCA,对操作排序,对每个颜色,节点按dfs序排序。然后扫一边,在每个颜色中,对每个节点颜色+1,这个节点和前一个节点的LCA颜色-1。最后DFS统计一下。下面代码实现使用dfs+st+sort,用dfs+tarjan
+基数排序可以做到线性复杂度。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 50005 #define maxm 100005 #define eps 1e-7i #define mod 1000000007 #define INF 0x3f3f3f3f #define PI (acos(-1.0)) #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R #define pii pair<int, int> #pragma comment(linker, "/STACK:16777216") typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} // head struct Edge { int v; Edge *next; }*H[maxn], *edges, E[maxm]; struct node { int c, u; }po[500005]; int first[maxn]; int ver[maxm]; int K[maxm]; int R[maxm]; int dp[maxm][20]; bool vis[maxn]; int ans[maxn]; int n, m, tot; void addedges(int u, int v) { edges->v = v; edges->next = H[u]; H[u] = edges++; } void init() { tot = 0; edges = E; memset(H, 0, sizeof H); memset(ans, 0, sizeof ans); memset(vis, 0, sizeof vis); } void read() { int u, v; for(int i = 1; i < n; i++) { scanf("%d%d", &u, &v); addedges(u, v); addedges(v, u); } for(int i = 0; i < m; i++) scanf("%d%d", &po[i].u, &po[i].c); } void dfs(int u, int dep) { vis[u] = true, ver[++tot] = u, first[u] = tot, R[tot] = dep; for(Edge *e = H[u]; e; e = e->next) if(!vis[e->v]) { int v = e->v; dfs(v, dep + 1); ver[++tot] = u, R[tot] = dep; } } void ST(int len) { K[0] = -1; for(int i = 1; i <= len; i++) K[i] = i & (i-1) ? K[i-1] : K[i-1] + 1; for(int i = 1; i <= len; i++) dp[i][0] = i; for(int j = 1; j <= K[len]; j++) for(int i = 1; i + (1 << j) - 1 <= len; i++) { int a = dp[i][j-1], b = dp[i + (1 << j - 1)][j-1]; dp[i][j] = R[a] < R[b] ? a : b; } } int rmq(int l, int r) { int k = K[r - l + 1]; int a = dp[l][k], b = dp[r - (1 << k) + 1][k]; return R[a] < R[b] ? a : b; } int lca(int u, int v) { int a = first[u], b = first[v]; if(a > b) swap(a, b); return ver[rmq(a, b)]; } void DFS(int u) { vis[u] = true; for(Edge *e = H[u]; e; e = e->next) if(!vis[e->v]) { int v = e->v; DFS(v); ans[u] += ans[v]; } } int cmp(node a, node b) { if(a.c == b.c) return first[a.u] < first[b.u]; else return a.c < b.c; } void work() { dfs(1, 0); ST(2 * n - 1); sort(po, po+m, cmp); for(int i = 0; i < m; i++) { ans[po[i].u]++; if(i && po[i-1].c == po[i].c) ans[lca(po[i].u, po[i-1].u)]--; } memset(vis, 0, sizeof vis); DFS(1); for(int i = 1; i <= n; i++) printf("%d%c", ans[i], i == n ? '\n' : ' '); } int main() { while(scanf("%d%d", &n, &m)!=EOF) { init(); read(); work(); } return 0; }