aoj2170(並查集操作更改)
阿新 • • 發佈:2018-12-30
/* translation: 給出一棵樹,根節點為1。一開始只有根節點被標記。現在有兩種操作,一種是查詢某一節點最近的一個標記 父節點,另外是將某一節點標記。求所有查詢父節點下標的和。 solution: 按照題意,依次父節點遍歷即可。 note: #這道題一開始被歸類為並查集,害得我想了半天。並查集的路徑壓縮會破壞樹的父子節點的關係而此題又要 維護父子節點的關係,形成矛盾。後來想可不可以不用路徑壓縮,又被自己否定了,因為題目沒說查詢的操作 最多多少個。萬一查詢數量過多的話肯定超時!沒想到最後正好是不用壓縮路徑做的。淚。這題目明顯不科學! 測試資料水。。。 date: 2016.10.19 */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 100000 + 5; typedef long long ll; int par[maxn], n, q; bool marked[maxn]; int ancestor(int x) { while(par[x] != x && !marked[x]) x = par[x]; return x; } int main() { //freopen("in.txt", "r", stdin); while(~scanf("%d%d", &n, &q)) { if(n == 0 && q == 0) break; memset(marked, 0, sizeof(marked)); for(int i = 1; i <= n; i++) par[i] = i; int p; marked[1] = true; for(int i = 2; i <= n; i++) { scanf("%d", &p); par[i] = p; } char op; int x; ll ans = 0; while(q--) { scanf("\n%c%d", &op, &x); if(op == 'M') marked[x] = true; else ans += ancestor(x); } printf("%lld\n", ans); } }