1. 程式人生 > >AOJ2170 Marked Ancestor【並查集】

AOJ2170 Marked Ancestor【並查集】

Marked Ancestor


Problem F:

You are given a treeTthat consists ofNnodes. Each node is numbered from 1 toN, and node 1 is always the root node ofT. Consider the following two operations onT:

  • M v: (Mark) Mark nodev.
  • Q v: (Query) Print the index of the nearest marked ancestor of nodevwhich is nearest to it. Initially, only the root node is marked.

Your job is to write a program that performs a sequence of these operations on a given tree and calculates the value that each Q operation will print. To avoid too large output file, your program is requested to print the sum of the outputs of all query operations. Note that the judges confirmed that it is possible to calculate every output of query operations in a given sequence.

Input

The input consists of multiple datasets. Each dataset has the following format:

The first line of the input contains two integersNandQ, which denotes the number of nodes in the treeTand the number of operations, respectively. These numbers meet the following conditions: 1 ≤N≤ 100000 and 1 ≤Q≤ 100000.

The followingN

- 1 lines describe the configuration of the treeT. Each line contains a single integerpi(i= 2, ... ,N), which represents the index of the parent ofi-th node.

The nextQlines contain operations in order. Each operation is formatted as "M v" or "Q v", wherevis the index of a node.

The last dataset is followed by a line containing two zeros. This line is not a part of any dataset and should not be processed.

Output

For each dataset, print the sum of the outputs of all query operations in one line.

Sample Input

6 3
1
1
2
3
3
Q 5
M 3
Q 5
0 0

Output for the Sample Input

4

問題簡述

  一棵樹有n個節點,每個節點標號為1到n,1是樹的根節點。有如下2種操作:

  M v:(標記)標記節點v。

  Q v:(查詢)列印與v節點距離最近的被標記的點的編號。開始時只有根節點被標記。

  輸入n-1個數表示,每個數是第i個數的父節點,輸出對於每個查詢得到標號的總和。

問題分析

  這是並查集與樹相結合的問題,輸入時根據父節點關係建立並查集,1的父節點是1。

  標記節點v即將該節點的子樹分離。

程式說明:(略)

題記:(略)

參考連結:(略)

AC的C++語言程式如下:

/* AOJ2170 Marked Ancestor */

#include <iostream>
#include <stdio.h>

using namespace std;

const int N = 1e5;
int f[N + 1];

void UFInit(int n)
{
    for(int i = 1; i <=n; i++)
        f[i] = i;
}

int Find(int a) {
    return a == f[a] ? a : Find(f[a]);
}

int main()
{
    int n, q, a;
    char op;

    while(~scanf("%d%d", &n, &q) && (n || q)) {
        UFInit(n);

        for(int i = 2; i <= n; i++)
            scanf("%d", &f[i]);

        long long ans = 0;
        for(int i = 1; i <= q; i++) {
            getchar();
            scanf("%c%d", &op, &a);

            if(op == 'Q')
                ans += Find(a);
            else if(op == 'M')
                f[a] = a;
        }

        printf("%lld\n", ans);
    }

    return 0;
}