Aizu:2170-Marked Ancestor
Marked Ancestor
Time limit 8000 ms
Memory limit 131072 kB
Problem Description
You are given a tree T that consists of N nodes. Each node is numbered from 1 to N, and node 1 is always the root node of T. Consider the following two operations on T:
M v: (Mark) Mark node v.
Q v: (Query) Print the index of the nearest marked ancestor of node v which 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 integers N and Q, which denotes the number of nodes in the tree T and the number of operations, respectively. These numbers meet the following conditions: 1 ≤ N ≤ 100000 and 1 ≤ Q ≤ 100000.
The following N - 1 lines describe the configuration of the tree T. Each line contains a single integer pi (i = 2, … , N), which represents the index of the parent of i-th node.
The next Q lines contain operations in order. Each operation is formatted as “M v” or “Q v”, where v is 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
解题心得:
- 题意就是有一棵树,有两种操作,第一种是将某个点标记,第二种是询问距离某个点被标记的最进的祖先节点的编号,最后需要你打印出所有询问编号的总和。
- 据说这题每次回溯跑暴力都能跑出来,因为时间给了八秒嘛,其实我感觉这是考了一个并查集关于树的变形
这样改变了树的深度,在询问答案的时候就可以O(1)得到答案,那怎么改变树的的形态呢。 - 其实可以将树的每个结点看成一颗新的树,每次标记的时候就可以将这个标记的节点看成根节点,形成一个子树,然后将它下面没有出现子树的部分全部合并起来。
#include <algorithm>
#include <stdio.h>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e5+100;
int father[maxn],n,m;
bool vis[maxn];
vector <int> ve[maxn];
void init() {
for(int i=1;i<=n;i++) {
ve[i].clear();
father[i] = 1;
vis[i] = false;
}
for(int i=2;i<=n;i++) {
int temp;
scanf("%d",&temp);
ve[temp].push_back(i);
}
vis[1] = true;
}
void dfs(int x,int fa) {
if(vis[x])
return ;
father[x] = fa;
for(int i=0;i<ve[x].size();i++) {
dfs(ve[x][i],fa);
}
}
void Mark(int x) {
vis[x] = true;
father[x] = x;
for(int i=0;i<ve[x].size();i++)
dfs(ve[x][i],x);
}
void Solve() {
long long sum = 0;
for(int i=0;i<m;i++) {
char temp[5];
int x;
scanf("%s%d",temp,&x);
if(temp[0] == 'M')
Mark(x);
else
sum += father[x];
}
printf("%lld\n",sum);
}
int main() {
while(scanf("%d%d",&n,&m) && n|m) {
init();
Solve();
}
return 0;
}
上一篇: 1053 Path of Equal Weight (30分)
下一篇: Aizu0121
推荐阅读
-
Cheese Aizu - 0558 (搜索题)
-
PAT甲级1143 Lowest Common Ancestor BST+LCA
-
1143 Lowest Common Ancestor 甲级
-
[C++] PAT 1143 Lowest Common Ancestor (30分)
-
⭐⭐⭐⭐⭐PAT A1143 Lowest Common Ancestor
-
PAT 1143 Lowest Common Ancestor 【C++版】
-
1143 Lowest Common Ancestor
-
pat-1143 Lowest Common Ancestor (30分)
-
1143 Lowest Common Ancestor (30分)
-
1143 Lowest Common Ancestor (30分)