題目鏈接:點我啊╭(╯^╰)╮
題目大意:
個點, 條邊, 次操作
每個點有一個集合, 裏最初只有自己
每次操作將第 條邊的兩個點的 合併
合併後兩個點的 爲合併後的
最後問每個點被幾個 包含
解題思路:
表示 與 的 大小,合併後:
表示兩個集合交,也就是上次合併的大小
問題來了,怎麼求每個點去過幾個 呢???
題解說倒過來求就是了
我的理解是倒過來的意義在於每次操作都是對後綴處理
表示 與 的能去多少個 ,合併後:
表示兩個點都能去的 個數
因爲是倒過來求
表示的就是完成後綴操作後
兩者能去的 個數
我還能說什麼
核心:正難則反
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
const int maxn = 5e5 + 5;
int n, m, p[maxn], f[maxn];
int gu[maxn], gv[maxn], g[maxn];
int main() {
scanf("%d%d", &n, &m);
for(int i=1; i<n; i++) scanf("%d%d", gu+i, gv+i);
for(int i=1; i<=m; i++) scanf("%d", p+i);
for(int i=1; i<=n; i++) f[i] = 1;
for(int i=m, u, v; i; i--){
u = gu[p[i]], v = gv[p[i]];
f[u] = f[v] = f[u] + f[v] - g[p[i]];
g[p[i]] = f[u];
}
for(int i=1; i<=n; i++) printf("%d%c", f[i], "\n "[i<n]);
}