Problem:
Problem F:
Marked Ancestor
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. Note that a node is an ancestor of itself.
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
p
i
(
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

Submitted solutions:

code_snippet: #include <cstdio>
#include <iostream>
#include <stack>
#include <cstring>
#include <vector>

using namespace std;

typedef pair<char, int> pci;

stack<pci> s;

int fa[100010];
int p[100010];
int vis[100010];

vector<int> e[100010];

int n;

void dfs(int i, int f = 1) {
  if(vis[i]) {
    f = i;
  }
  fa[i] = f;
  vector<int> &ei = e[i];
  for(vector<int>::iterator it = ei.begin(); it != ei.end(); ++it) {
    dfs(*it, f);
  }
}

int find(int x) {
  if(x == fa[x]) return x;
  return fa[x] = find(fa[x]);
}

int main() {
  int i, j, q;
  long long ans;
  char op[3];
  while(scanf("%d%d", &n, &q) != EOF && n > 0) {
    memset(vis, 0, sizeof(vis));
    for(i = 1; i <= n; ++i) {
      e[i].clear();
    }
    ans = 0;

    vis[1] = 1;
    for(i = 2; i <= n; ++i) {
      scanf("%d", &j);
      e[j].push_back(i);
      p[i] = j;
    }
    for(i = 0; i < q; ++i) {
      scanf("%s%d", op, &j);
      if(op[0] == 'M') {
        ++vis[j];
      }
      s.push(make_pair(op[0], j));
    }
    dfs(1);

    while(!s.empty()) {
      i = s.top().second;
      if(s.top().first == 'M') {
        if(--vis[i] == 0) {
          fa[i] = find(p[i]);
        }
      } else {
        ans += find(i);
      }
      s.pop();
    }

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

  }
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 14152
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class tree{
    public:
    vector<int> p;
    vector<bool> q;
    tree(){};
    tree(int size){
        p.resize(size+1,0);
        q.resize(size+1,0);
        for(int i=0;i<=size;i++){
            makenew(i);
        }
    }
    void makenew(int a){
        p[a]=1;
    }
    int find(int a){
        while(q[a]==false){
            a=p[a];
        }
        return a;
    }    
};
int main(){
    int n,q;
    while(cin>>n>>q&&n!=0&&q!=0){
    tree pq=tree(n);
    long long ans=0;
    for(int i=2;i<=n;i++){
        int x;
        cin>>x;
        pq.p[i]=x;
    }
    pq.q[1]=true;
    for(int i=0;i<q;i++){
        char ch;
        cin>>ch;
        if(ch=='M'){
            int x;
            cin>>x;
            pq.q[x]=true;
        }else if(ch=='Q'){
            int x;
            cin>>x;
            int t=pq.find(x);
            ans+=t;
        }
    }
        cout<<ans<<endl;}
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 3580
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

// 存储树的结构和标记
struct Tree {
    vector<int> P;       // P[i]: 节点 i 的父节点
    vector<bool> Marked; // Marked[v]: 节点 v 是否被标记
    int N;

    Tree(int size) : N(size) {
        // 数组大小为 N+1，用于 1-based 索引
        P.resize(N + 1, 0);
        Marked.resize(N + 1, false);

        // 初始化根节点 1
        Marked[1] = true; 
        P[1] = 1; // 根节点的父节点设为自己，作为循环的哨兵
    }
};

// 查找函数：O(N) 暴力向上遍历
// 这是逻辑上最简单且正确的实现
int find_nearest_marked(const Tree& t, int v) {
    int current = v;
    
    // 循环向上查找
    // 1. 如果 Marked[current] == true，循环停止，返回 current
    // 2. 如果 Marked[current] == false，向上跳： current = t.P[current]
    // 
    // 由于 Marked[1] == true 且 P[1] == 1，循环保证会在根节点停止。
    while (t.Marked[current] == false) {
        current = t.P[current];
    }
    
    // 找到了第一个标记的祖先（或节点自身）
    return current;
}


void solve() {
    int N, Q;
    // 循环读取多个数据集
    while (cin >> N >> Q && (N != 0 || Q != 0)) {
        Tree t(N);
        
        // 1. 读取树的结构 (P[i] 存储 i 的父节点)
        for (int i = 2; i <= N; ++i) {
            cin >> t.P[i];
        }
        
        long long total_sum = 0;

        // 2. 执行 Q 次操作
        for (int i = 0; i < Q; ++i) {
            char ch;
            int x;
            cin >> ch >> x;

            if (ch == 'M') {
                // M x (标记操作): O(1)
                t.Marked[x] = true;
            } else if (ch == 'Q') {
                // Q x (查询操作): O(N) 
                int nearest_marked = find_nearest_marked(t, x);
                total_sum += nearest_marked;
            }
        }
        
        cout << total_sum << endl;
    }
}

int main() {
    // 禁用同步，加速 IO
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    solve();
    
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3768
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct DSU{
  vector<int> par;
  int N;
  DSU(int _N):N(_N),par(_N,-1){}
  int root(int x){
    if(par[x]==-1) return x;
    else return par[x]=root(par[x]);
  }
  void merge(int x,int y){
    x=root(x),y=root(y);
    if(x==y)return;
    par[x]=y;
  }
  bool same(int x,int y){
    return root(x)==root(y);
  }
};


int N,Q;
char com[3<<17];
int A[3<<17];
int P[3<<17];
int marked[3<<17];
int unused[3<<17];

int main(){

  while(1){
    scanf("%d%d",&N,&Q);
    memset(marked,0,sizeof(marked));
    memset(unused,0,sizeof(unused));
    vector<vector<int>> G(N);
    if(N==0&&Q==0) return 0;
    for(int i=1;i<N;i++){
      int p; scanf("%d",&p);
      p--;
      P[i]=p;
      G[p].push_back(i);
    }

    for(int i=0;i<Q;i++){
      scanf(" %c",&com[i]);
      scanf("%d",&A[i]);
      if(com[i]=='M'){
        if(marked[A[i]-1]){
          unused[i]=1;
        }
        else{
          marked[A[i]-1]=1;
        }
      }
    }

    DSU uf(N);

    auto dfs = [&](auto dfs,int v)->void{
      for(auto nv : G[v]){
        if(!marked[nv]){
          uf.merge(nv,v);
        }
        dfs(dfs,nv);
      }
    };
    dfs(dfs,0);



    long long ans = 0;
    for(int i=Q-1;i>=0;i--) if(!unused[i]){
      if(com[i]=='Q'){
        ans += uf.root(A[i]-1)+1;
      }
      else{
        uf.merge(A[i]-1,P[A[i]-1]);
      }
    }
    printf("%lld\n",ans);
  }



}
accuracy: 1
time_ms: 100
memory_kb: 29632
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int N=1e5+100;
struct node1{
	char opt; 
    ll v;
}qq[N];
struct node2{
	ll cnt,rt;
}fa[N];
ll n,q,to[N];
ll find(ll x){ 
    if(fa[x].rt==x) return x;
    else return fa[x].rt=find(fa[x].rt); 
}
inline void merge(ll a,ll b){
	ll ra=find(a),rb=find(b);
	if(ra!=rb) fa[ra].rt=rb;
}
inline void init(){
	memset(fa,0,sizeof fa);
	memset(to,0,sizeof to);
	memset(qq,0,sizeof q);
	fa[1].rt=1,fa[1].cnt=1;
}
inline void solve(){
	init();
	for(int i=2;i<=n;++i){
		std::cin>>fa[i].rt;
		to[i]=fa[i].rt;
	}
	for(int i=1;i<=q;++i){
		std::cin>>qq[i].opt>>qq[i].v;
		if(qq[i].opt=='M') fa[qq[i].v].rt=qq[i].v,fa[qq[i].v].cnt++;
		else continue;
	}
	ll ans=0;
	for(int i=q;i>=1;--i){
	 	auto [opt,v]=qq[i];
	 	if(opt=='Q') ans+=find(v);
	 	else{
	 		fa[v].cnt--;
	 		if(!fa[v].cnt) fa[v].rt=to[v];
 	 	}
	}
	std::cout<<ans<<"\n";
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cout.tie(0);
	while(1){
		std::cin>>n>>q;
		if(!n and !q) break;
		solve();
	}
}
accuracy: 1
time_ms: 50
memory_kb: 7520
final_rank: 2

code_snippet: #define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include<vector>
using namespace std;

const int M = 100010;
int n, q, ct, fa[M], d[M], sz[M], sn[M], tp[M], df[M], tr[M << 2], stk[M], cur[M];
char op[2];
stack<int> S;
vector<int> G[M];

void dfs1() {
    S.push(1); d[1] = 1; fa[1] = 0;
    while (!S.empty()) {
        int u = S.top();
        if (!cur[u])sz[u] = 1;
        if (cur[u] < G[u].size()) {
            int v = G[u][cur[u]++];
            d[v] = d[u] + 1; fa[v] = u;
            S.push(v);
        }
        else {
            S.pop();
            if (u > 1) {
                sz[fa[u]] += sz[u];
                if (sz[u] > sz[sn[fa[u]]])sn[fa[u]] = u;
            }
        }
    }
}

void dfs2() {
    ct = 0; stack<pair<int, int> > T; T.push({ 1,1 });
    while (!T.empty()) {
        int u = T.top().first, t = T.top().second; T.pop();
        df[u] = ++ct; tp[u] = t;
        for (int i = G[u].size() - 1; i >= 0; --i) {
            int v = G[u][i];
            if (v == sn[u])continue;
            T.push({ v,v });
        }
        if (sn[u])T.push({ sn[u],t });
    }
}

void upd(int p, int v, int l = 1, int r = n, int o = 1) {
    if (l == r) { tr[o] = v; return; }
    int m = l + r >> 1;
    p <= m ? upd(p, v, l, m, o << 1) : upd(p, v, m + 1, r, o << 1 | 1);
    int a = tr[o << 1], b = tr[o << 1 | 1];
    tr[o] = (a && b) ? (d[a] > d[b] ? a : b) : (a ? a : b);
}

int qry(int L, int R, int l = 1, int r = n, int o = 1) {
    if (L <= l && r <= R)return tr[o];
    int m = l + r >> 1, a = 0, b = 0;
    if (L <= m)a = qry(L, R, l, m, o << 1);
    if (R > m)b = qry(L, R, m + 1, r, o << 1 | 1);
    return a && b ? (d[a] > d[b] ? a : b) : (a ? a : b);
}

int qp(int v) {
    int r = 0;
    while (v) {
        int t = qry(df[tp[v]], df[v]);
        if (t && (!r || d[t] > d[r]))r = t;
        v = fa[tp[v]];
    }
    return r;
}

int main() {
    while (scanf("%d%d", &n, &q), n || q) {
        for (int i = 1; i <= n; ++i) G[i].clear(), sn[i] = cur[i] = 0;
        for (int i = 2, p; i <= n; ++i) scanf("%d", &p), G[p].push_back(i);
        dfs1(); dfs2();
        memset(tr, 0, sizeof tr); upd(df[1], 1);
        long long sm = 0;
        while (q--) {
            scanf("%s%d", op, &stk[0]);
            if (*op == 'Q')sm += qp(stk[0]);
            else upd(df[stk[0]], stk[0]);
        }
        printf("%lld\n", sm);
    }
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 14660
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
int n, m, a[100005];
bool vis[100005];
int find(int x) {
	if (vis[x] == true) {
		return x;
	} else {
		return find(a[x]);
	}
}
int main() {
	while (1) {
		cin >> n >> m;
		if (n == 0 && m == 0) {
			return 0;
		}
		long long sum = 0;
		memset(vis,0,sizeof vis);
		memset(a,0,sizeof a);
		a[1] = 1;
		for (int i = 2; i <= n; i++) {
			cin >> a[i];
		}
		vis[1] = true;
		while (m--) {
			char s;
			int x;
			cin >> s >> x;
			if (s == 'M') {
				vis[x] = true;
			} else {
				sum += find(x);
			}
		}
		cout << sum << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3808
final_rank: 15

code_snippet: #include <vector>
#include<cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <deque>
#include <set>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <unordered_map>
#include <cassert>
#endif
#include <ctime>
#include <queue>
#include <stack>
#include<iomanip>
#include <sstream>
#include <cmath>
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const ll mod = 1000000007;

struct SegTree {
    vector<int> c;
    void init(int n) {
        c.assign(n << 2, 1);
    }
    void pushDown(int rt, int L, int R, int l, int r, int x, vector<PII>& seg) {
        if (c[rt << 1] == -1 || seg[c[rt << 1]].first <= seg[c[rt]].first
            && seg[c[rt]].second <= seg[c[rt << 1]].second) {
            c[rt << 1] = c[rt];
        }
        if (c[rt << 1|1] == -1 || seg[c[rt << 1|1]].first <= seg[c[rt]].first
            && seg[c[rt]].second <= seg[c[rt << 1|1]].second) {
            c[rt << 1|1] = c[rt];
        }
    }
    void update(int rt, int L, int R, int l, int r, int x, vector<PII>& seg) {

        if (l <= L && R <= r) {
            if (c[rt] == -1 || seg[c[rt]].first <= l && r <= seg[c[rt]].second) {
                c[rt] = x;
            }
            //printf("rt = %d, c[rt] = %d\n", rt, c[rt]);
            return;
        }
        pushDown(rt, L, R, l, r, x, seg);
        int m = L + R >> 1;
        if (m >= l) update(rt << 1, L, m, l, r, x, seg);
        if (m + 1 <= r) update(rt << 1 | 1, m + 1, R, l, r, x, seg);
    }
    void query(int rt, int L, int R, int x, vector<PII>& seg, int& ans) {
        //printf("debug rt = %d, L = %d, R = %d, x = %d, ans = %d, c[rt] = %d\n", rt, L, R, x, ans, c[rt]);
        if (c[rt] != -1) {

            if (ans == -1 || seg[ans].first <= seg[c[rt]].first && seg[c[rt]].second <= seg[ans].second) {
                ans = c[rt];
            }
        }
        if (L == R) return;
        int m = L + R >> 1;
        if (x <= m) query(rt << 1, L, m, x, seg, ans);
        if (m + 1 <= x) query(rt << 1 | 1, m + 1, R, x, seg, ans);
    }
}segtree;
vector<vector<int> > tree;
void dfs_sons(int root, vector<int>& cnt) {
    cnt[root] = 1;
    for(int i = 0; i < tree[root].size(); i ++) {
        dfs_sons(tree[root][i], cnt);
        cnt[root] += cnt[tree[root][i]];
    }
}
void dfs(int root, vector<PII>& seg, vector<int>& cnt, int l, int r) {
    seg[root] = PII(l, r);
    int s = l;
    for(int i = 0; i < tree[root].size(); i ++) {
        int e = s + cnt[tree[root][i]];
        dfs(tree[root][i], seg, cnt, s, e - 1);
        s = e;
    }
}
void solve(int ncase) {
    int n, m;
    while(scanf("%d%d", &n, &m) == 2 && !(n == 0 && m == 0)) {
        //printf("%d %d\n", n, m);
        // form tree
        tree.assign(n + 1, vector<int>());
        for(int i = 2; i <= n; i ++) {
            int pre;
            scanf("%d", &pre);
            tree[pre].push_back(i);
        }
        // form seg from point
        vector<PII> seg(n + 1);
        vector<int> cnt(n + 1);
        dfs_sons(1, cnt);
        dfs(1, seg, cnt, 1, n);
        //for(auto p : seg) cout << p.first << " - " << p.second << endl;
        // init seg tree
        segtree.init(n);
        // process query Q / M
        char op[2];
        vector<int> marker(n + 1);
        marker[1] = 1;
        int x;
        ll sum = 0;
        for(int i = 0; i < m; i ++) {
            scanf("%s%d", &op, &x);
            if (op[0] == 'Q') {
                int ans = -1;
                segtree.query(1, 1, n, seg[x].second, seg, ans);
                //printf("Q %d = %d\n", x, ans);
                sum += ans;
            } else {
               // printf("M %d\n", x);
                if (marker[x]) continue;
                marker[x] = 1;
                segtree.update(1, 1, n, seg[x].first, seg[x].second, x, seg);
            }
        }
        printf("%lld\n", sum);
    }
}


int main() {
    //ios::sync_with_stdio(false);
    //cout << setprecision(16) << endl;
#ifdef _zzz_
   freopen("1.in", "r", stdin);
   //freopen("out.txt", "w", stdout);
#endif
    int T = 1;
    //scanf("%d", &T);
    //cin >> T;
    int ncase = 0;
    while(T --) {
        solve(++ ncase);
    }
}
accuracy: 1
time_ms: 140
memory_kb: 16940
final_rank: 16

code_snippet: #include <vector>
#include<cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <deque>
#include <set>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <unordered_map>
#include <cassert>
#endif
#include <ctime>
#include <queue>
#include <stack>
#include<iomanip>
#include <sstream>
#include <cmath>
using namespace std;
typedef pair<int, int> PII;
typedef pair<int, PII> PIP;
typedef long long ll;
const ll mod = 1000000007;

struct DisjointSet {
    vector<int> pre;
    void init(int n) {
        pre.assign(n, -1);
    }
    int root(int x) {
        int r = x;
        while(pre[r] >= 0) r = pre[r];
        return r;
    }
    void join(int a, int b) {
        int ra = root(a);
        int rb = root(b);
        if (ra != rb) {
            int na = -pre[ra];
            int nb = -pre[rb];
            pre[ra] = rb;
            pre[rb] = -(na + nb);
        }
    }
    bool test(int a, int b) {
        return root(a) == root(b);
    }
}djs;
void solve(int ncase) {
    int n, m;
    while(scanf("%d%d", &n, &m) == 2 && !(n == 0 && m == 0)) {
        vector<int> fa(n + 1);
        for(int i = 2; i <= n; i ++) {
            scanf("%d", &fa[i]);
        }
        vector<int> mark(n + 1);
        mark[1] = 1;
        djs.init(n + 1);
        vector<PII> op;
        for(int i = 0; i < m; i ++) {
            char s[2];
            int x;
            scanf("%s%d", s, &x);
            if (s[0] == 'Q') {
                op.push_back(PII(1, x));
            } else if (mark[x] == 0) {
                mark[x] = 1;
                op.push_back(PII(2, x));
            }
        }

        for(int i = 1; i <= n; i ++) {
            if (mark[i] == 0) {
                djs.join(i, fa[i]);
            }
        }
        ll sum = 0;
        for(int i = op.size() - 1; i >= 0; i --) {
            if (op[i].first == 1) {
                sum += djs.root(op[i].second);
            } else {
                djs.join(op[i].second, fa[op[i].second]);
            }
        }
        printf("%lld\n", sum);
    }
}


int main() {
    //ios::sync_with_stdio(false);
    //cout << setprecision(16) << endl;
#ifdef _zzz_
   //freopen("1.in", "r", stdin);
   //freopen("10.out", "w", stdout);
#endif
    int T = 1;
    //scanf("%d", &T);
    //cin >> T;
    int ncase = 0;
    while(T --) {
        solve(++ ncase);
    }
}
accuracy: 1
time_ms: 70
memory_kb: 6236
final_rank: 3

code_snippet: //
// Create by Running Photon on 2015-03-20
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;

#define CLR(x) memset(x,0,sizeof x)
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int MOD=5e5+5;
int n, m;
int par[maxn];
int Find(int x)
{
    if(par[x] == x) return x;
    else return Find(par[x]);
}
int main()
{
#ifdef LOCAL
	freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
#endif
	ios_base::sync_with_stdio(0);

	while(scanf("%d%d", &n, &m) != EOF && n && m){
        par[1] = 1;
        int x, u;
        ll sum = 0;
        char c[2];
        par[1] = 1;
        for(int i = 2; i <= n; i++) scanf("%d", par + i);
        for(int i = 1; i <= m; i++){
            scanf("%s%d", c, &u);
            if(c[0] == 'Q') sum += Find(u);
            else par[u] = u;
        }
        printf("%lld\n", sum);
	}
	return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3872
final_rank: 6

code_snippet: //
// Create by Running Photon on 2015-03-20
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;

#define CLR(x) memset(x,0,sizeof x)
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int MOD=5e5+5;
int n, m;
int par[maxn];
bool mark[maxn];
int Find(int x)
{
    if(mark[x]) return x;
    else return Find(par[x]);
}
int main()
{
#ifdef LOCAL
	freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
#endif
	ios_base::sync_with_stdio(0);

	while(scanf("%d%d", &n, &m) != EOF && n && m){
        CLR(par);
        CLR(mark);
        mark[1] = true;
        int x, u;
        ll sum = 0;
        char c[2];
        par[1] = 1;
        for(int i = 2; i <= n; i++) scanf("%d", par + i);
        for(int i = 1; i <= m; i++){
            scanf("%s%d", c, &u);
            if(c[0] == 'Q'){
                sum += Find(u);
            }
            else{
                mark[u] = true;
            }
        }
        printf("%lld\n", sum);
	}
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 3972
final_rank: 8

code_snippet: //
//  AOJ 2170 Marked Ancestor
//
//  Created by TaoSama on 2015-03-16
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
#define CLR(x,y) memset(x, y, sizeof(x))

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, q, par[N], rank[N];
bool marked[N];

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

int find(int x) {
	if(marked[x]) return x;
	return find(par[x]);
}

int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	ios_base::sync_with_stdio(0);

	while(~scanf("%d%d", &n, &q) && n && q) {
		init(n);
		memset(marked, false, sizeof marked);
		marked[1] = true;
		for(int i = 2; i <= n; ++i) {
			int x; scanf("%d", &x);
			par[i] = x;
		}
		long long ans = 0;
		for(int i = 1; i <= q; ++i) {
			char op[2]; int x;
			scanf("%s%d", op, &x);
			if(op[0] == 'Q') {
				ans += find(x);
			} else {
				marked[x] = true;
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 3768
final_rank: 7

code_snippet: // 問題：https://onlinejudge.u-aizu.ac.jp/problems/2170
//　判定：AC

//学習コメント：

#include <bits/stdc++.h>
#include <vector>
#include <cmath>
using namespace std;
int main() {
    int N,Q,x;
    string Y;
    cin >> N >> Q;
    while(N != 0 or Q != 0){
        vector<int>P(N,0);
        vector<bool>M(N,false);
        long long ans =0;
        M[0] = true;
        P[0] = 0;
        for(int i=1;i<N;i++){
            cin >> x;
            P[i] = x-1;
            M[i] = false;
        }
        for(int i=0;i<Q;i++){
            cin >> Y >> x;
            if(Y == "M"){
                M[x-1] = true;
            }
            if(Y == "Q"){
                int u = x-1;
                while(!M[u]){
                    u = P[u];
                }
                ans += u+1;

            }
        }
        cin >> N >> Q;
        cout << ans << endl;
    }

}
accuracy: 1
time_ms: 260
memory_kb: 3744
final_rank: 17

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
struct DSU {
    std::vector<int> par;
    DSU(int n) : par(n) {
        std::iota(par.begin(), par.end(), 0);
    }
    int leader(int v) {
        return par[v] == v ? v : par[v] = leader(par[v]);
    }
    // uが親側
    void merge(int u, int v) {
        u = leader(u);
        v = leader(v);
        if (u == v) return;
        par[v] = u;
    }
};
int N, Q, T[100010], V[100010], ans[100010], par[100010];
bool solve() {
    std::cin >> N >> Q;
    if (N == 0 and Q == 0) return false;
    for (int i = 1 ; i < N ; i++) {
        std::cin >> par[i];
        par[i]--;
    }
    std::vector<int> marked(N);
    for (int i = 0 ; i < Q ; i++) {
        char c;
        std::cin >> c >> V[i];
        V[i]--;
        T[i] = (c == 'Q' ? 1 : 0);
        if (T[i] == 0) marked[V[i]]++;
    }
    DSU dsu(N);
    for (int i = 1 ; i < N ; i++) if (marked[i] == 0) {
        dsu.merge(par[i], i);
    }
    long long ans = 0;
    for (int i = Q - 1 ; i >= 0 ; i--) {
        if (T[i] == 0) {
            marked[V[i]]--;
            if (marked[V[i]] == 0) dsu.merge(par[V[i]], V[i]);
        }
        else {
            ans += dsu.leader(V[i]) + 1;
        }
    }
    std::cout << ans << '\n';
    return true;
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    while (solve()) ;
}
accuracy: 1
time_ms: 40
memory_kb: 5376
final_rank: 1

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using pii = pair<int,int>;

int main(){
    cin.tie(nullptr);
	ios::sync_with_stdio(false);
	while(true){
	int n,q;
	cin >> n >> q;
	if ( n == 0){
		break;
	}
	vector<int>parent(n);
	vector<bool>visited(n,false);
	parent[0] = 0;
	visited[0] = true;
	for ( int i = 0; i < n - 1; i++){
		int temp;
		cin >> temp;
		parent[i + 1] = temp - 1;
	}
	i64 ans = 0;
	while(q--){
		char op;
		int x;
		cin >> op >> x;
		if ( op == 'M'){
			visited[x - 1] = true;
		} else{
			if ( visited[x - 1]){
				ans += x;
			} else{
				int par = parent[x - 1];
				while(!visited[par]){
					par = parent[par];
				}
				ans += (par + 1);
			}
		}
	}
	cout << ans << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3784
final_rank: 5

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,n) for(ll i = 0;i < (ll)n;i++)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


template<typename T>
class Segtree{
  public:
  using F = function<T(T,T)>;
  int n,real_n;
  F f;
  T ti;
  vector<T> dat;
  Segtree(){};
  Segtree(F f,T ti): f(f),ti(ti){}
  void init(int N){
    n = 1;
    while(n < N)n <<= 1;
    dat.assign(n << 1,ti);
  }
  void build(const vector<T> &v){
    real_n = v.size();
    init(real_n);
    for(int i = 0;i < real_n;i++)dat[n+i] = v[i];
    for(int i = n-1;i >= 0;i--)dat[i] = f(dat[(i << 1)|0],dat[(i << 1)|1]);
  }
  void set(int k,T x){
    dat[k+=n] = x;
    while(k >>= 1){
      dat[k] = f(dat[(k << 1)|0],dat[(k << 1)|1]);
    }
  }
  T get(int l,int r){
    T vl = ti,vr = ti;
    for(l += n,r += n;l < r;l >>= 1,r >>= 1){
      if(l & 1)vl = f(vl,dat[l++]);
      if(r & 1)vr = f(dat[--r],vr);
    }
    return f(vl,vr);
  }

  T operator[](const int &k)const{return dat[k+n];}
  
  // [l,x)がcheckを満たす最初の要素位置x. 存在しないとき real_n
  template<typename C>
  int find_first(int l,const C &check)const{
    if(l >= real_n)return real_n;
    l += n;
    T sum = ti;
    do{
      while((l & 1) == 0)l >>= 1;
      if(check(f(sum,dat[l]))){
        while(l < n){
          l <<= 1;
          auto nxt = f(sum,dat[l]);
          if(not check(nxt)){
            sum = nxt;l++;
          }
        }
        return l + 1 - n;
      }
      sum = f(sum,dat[l++]);
    }while((l & -l) != l);
    return real_n;
  }
  // [x,r)がcheckを満たす最後の要素位置x. 存在しないとき-1
  template<typename C>
  int find_last(int r,const C &check)const{
    if(r <= 0)return -1;
    r += n;
    T sum = ti;
    do{
      r--;
      while(r > 1 && (r & 1))r >>= 1;
      if(check(f(dat[r],sum))){
        while(r < n){
          r = (r << 1) + 1;
          auto nxt = f(dat[r],sum);
          if(not check(nxt)){
            sum = nxt;r--;
          }
        }
        return r-n;
      }
      sum = f(dat[r],sum);
    }while((r & -r) != r);
    return -1;
  }
};
// https://beet-aizu.github.io/library/tree/heavylightdecomposition.cpp
// セグ木の初期化はhld.id[hoge]をかませるのを忘れない！
struct HLD{
  /*
  v := 隣接リスト
  id := 元々の頂点のHLD後の頂点番号。
  head := heavyな辺でつながれた頂点集合の代表元。もっとも浅い頂点。
  sub_sz := 部分木のサイズ
  par := 親
  inv := HLD後の頂点番号から元々の頂点番号をかえす

  add_edge(a,b) := a,b間の無向辺を追加
  build() := HLD 分解を実行。内部でdfs_szによる部分木の取得、dfs_hldによるHLD実行。
  lca(a,b) := a,bのLCAを返す
  for_each(a,b,f) := 頂点a,b間の頂点(a,bを含む)にfを実行。このfにseg木などが乗る。
  for_each_edge(a,b,f) := 頂点a,b間の辺にfを実行。辺はつながっている２つの頂点の内深い方と対応させる。
  */
  vector<vector<int>> v;
  vector<int> id,head,sub_sz,par,inv;
  HLD(int n) : v(n),id(n,-1),head(n),sub_sz(n,1),par(n,-1),inv(n){}

  void add_edge(int a,int b){
    v[a].push_back(b);
    v[b].push_back(a);
  }

  void dfs_sz(int ov,int pre){
    if(v[ov].size() && v[ov][0] == pre)swap(v[ov][0],v[ov].back());
    par[ov] = pre;
    for(auto &nv : v[ov]){
      if(nv == pre)continue;
      dfs_sz(nv,ov);
      sub_sz[ov] += sub_sz[nv];
      if(sub_sz[nv] > sub_sz[v[ov][0]])swap(nv,v[ov][0]);
    }
  }
  void dfs_hld(int ov,int &pos){
    id[ov] = pos++;
    inv[id[ov]] = ov;
    for(auto nv : v[ov]){
      if(nv == par[ov])continue;
      head[nv] = (nv == v[ov][0] ? head[ov] : nv);
      dfs_hld(nv,pos);
    }
  }
  void build(int root = 0){
    int pos = 0;
    dfs_sz(root,-1);
    head[root] = root;
    dfs_hld(root,pos);
  }
  int lca(int a,int b){
    while(1){
      if(id[a] > id[b])swap(a,b);
      if(head[a] == head[b])return a;
      b = par[head[b]];
    }
  }
  /*
  関数内でfは半開区間で値を取得するように正規化するので，
  BITが閉区間で実装されている場合などは
  auto f = [&](int a,int b){return bit.sum(a,b-1);};
  の様に変更する．データ構造が半開区間で値を取得する場合は
  auto f = [&](int a,int b){return seg.get(a,b);};
  でよい．
  実装を見ればわかるが，a,bに対応する部分は
  hld.idで正規化されて渡されているので外部でfの宣言をするために正規化する必要はない.
  */
  template<typename F>
  void for_each(int a,int b,const F& f){
    while(1){
      if(id[a] > id[b])swap(a,b);
      f(max(id[head[b]],id[a]),id[b]+1);
      if(head[a] != head[b])b = par[head[b]];
      else break;
    }
  }
  template<typename F>
  void for_each_edge(int a,int b,const F& f){
    while(1){
      if(id[a] > id[b])swap(a,b);
      if(head[a] != head[b]){
        f(id[head[b]],id[b]+1);
        b = par[head[b]];
      }else{
        if(a != b)f(id[a]+1,id[b]+1);
        break;
      }
    }
  }
};

bool solve(){
  int n,Q;cin >> n >> Q;
  if(!n)return false;
  ve v(n);
  HLD hld(n);
  rep(i,n-1){
    int p;cin >> p;p--;
    v[p].emplace_back(i+1);
    v[i+1].emplace_back(p);
    hld.add_edge(i+1,p);
  }
  vi idx(n),inv(n);
  auto dfs = [&](auto &dfs,int ov,int pre,int &k)->void{
    idx[ov] = k++;
    inv[k-1] = ov;
    for(auto nv : v[ov]){
      if(nv == pre)continue;
      dfs(dfs,nv,ov,k);
    }
  };
  {
    int k = 0;
    dfs(dfs,0,-1,k);
  }
  auto f = [](int a,int b){return max(a,b);};
  Segtree<int> seg(f,-1);
  seg.build(vector<int>(2*n,-1));
  hld.build();
  seg.set(hld.id[0],0);
  ll res = 0;
  rep(_,Q){
    char c;int ov;cin >> c >> ov;
    ov--;
    if(c == 'M'){
      seg.set(hld.id[ov],idx[ov]);
    }else{
      int k = -1;
      auto f = [&](int a,int b){chmax(k,seg.get(a,b));};
      hld.for_each(0,ov,f);
      res += inv[k] + 1;
    }
  }
  cout << res << "\n";
  return true;
}

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  while(solve());
  

  return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 28924
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int f[100009];
int n , q;
bool vis[100009];
int find(int x)
{
	while(x != f[x]) x = f[x];
	return f[x];
}
int main()
{
	while(cin >> n >> q) //n个结点 q次询问 
	{
		if(n + q == 0)	break;
		f[1] = 1;
		for(int i = 2; i <= n; i++)
		{
			int x;
			cin >> x;  //结点i的父结点为x
			f[i] = x; 
		} 
		long long sum = 0;
		while(q--)
		{
			char op;
			int x;
			cin >> op >> x;
			if(op == 'M')  //标记 
				f[x] = x;
			else
				sum += find(x);
		}
		cout << sum << endl;
	}
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3744
final_rank: 11

code_snippet: #include<iostream>      // 又犯错了 思路真的很简单，是数据量的范围问题
                        //形如 long long c,int a
						// c+=a; 的结果是合理的   太大意了，粗略的估计还是判断错了 
#include<stdio.h>
using namespace std;
#define MAX_N 100005

int Par[MAX_N];
int Mark[MAX_N];
int N,Q;
long long ans;

void unite(int x,int y)
{
     	Par[y]=x;
}

int main()
{
	while(scanf("%d%d",&N,&Q)&&(N&&Q))
	{
	 ans=0;
	int num;
	char c1;
	Mark[1]=1;
	for(int i=2;i<=N;++i)
	{
		Mark[i]=0;
	}
	for(int i=2;i<=N;++i)
	{
		scanf("%d",&num);
		unite(num,i);
	}
	for(int i=0;i<Q;++i)
   {
   	  cin>>c1;
   	  scanf("%d",&num);
   	  if(c1=='M')
   	  {
   	  	Mark[num]=1;
	  }
	  else
	  {
	  	  int tmp=0;
	  	  while(Par[num]!=num)
	  	  {
	  	  	if(Mark[num])
	  	  	{
	  	  	  tmp=num;
	  	  	  ans+=tmp;
			  break;	
			}
	  	  	num=Par[num];
		  }
	     if(tmp==0)
	        ans+=1;

	  }
     }
     printf("%lld\n",ans);
  }
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3972
final_rank: 14

code_snippet: #include<iostream>      //去他妈的 又犯错了 思路真的很简单，是数据量的范围问题
                        //形如 long long c,int a
						// c+=a; 的结果是合理的   太大意了，粗略的估计还是判断错了 
#include<stdio.h>
using namespace std;
#define MAX_N 100005

int Par[MAX_N];
int Mark[MAX_N];
int N,Q;
long long ans;


/*
int find(int x)
{
	if(Par[x]==x)
	return x;
	else
	return find(Par[x]);
}
*/

void unite(int x,int y)
{
     	Par[y]=x;
}

int main()
{
	while(scanf("%d%d",&N,&Q)&&(N&&Q))
	{
	 ans=0;
	int num;
	char c1;
	Mark[1]=1;
	for(int i=2;i<=N;++i)
	{
		Mark[i]=0;
	}
	for(int i=2;i<=N;++i)
	{
		scanf("%d",&num);
		unite(num,i);
	}
	for(int i=0;i<Q;++i)
   {
   	  cin>>c1;
   	  scanf("%d",&num);
   	  if(c1=='M')
   	  {
   	  	Mark[num]=1;
	  }
	  else
	  {
	  	  int tmp=0;
	  	  while(Par[num]!=num)
	  	  {
	  	  	if(Mark[num])
	  	  	{
	  	  	  tmp=num;
			  break;	
			}
	  	  	num=Par[num];
		  }
	     if(tmp==0)
	        ans+=1;
		 else
		    ans+=tmp;
	  }
     }
     printf("%lld\n",ans);
  }
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3924
final_rank: 13

code_snippet: #include<iostream>      //去他妈的 又犯错了 思路真的很简单，是数据量的范围问题
                        //形如 long long c,int a
						// c+=a; 的结果是合理的   太大意了，粗略的估计还是判断错了 
#include<stdio.h>
using namespace std;
#define MAX_N 100005

int Par[MAX_N];
int Mark[MAX_N];
int N,Q;
long long ans;


void init(int n)
{
	for(int i=0;i<n;++i)
	{
		Par[i]=i;
	}
}
/*
int find(int x)
{
	if(Par[x]==x)
	return x;
	else
	return find(Par[x]);
}
*/

void unite(int x,int y)
{
     	Par[y]=x;
}

int main()
{
	while(scanf("%d%d",&N,&Q)&&(N&&Q))
	{
	 ans=0;
	init(N+1);
	int num;
	char c1;
	Mark[1]=1;
	for(int i=2;i<=N;++i)
	{
		Mark[i]=0;
	}
	for(int i=2;i<=N;++i)
	{
		scanf("%d",&num);
		unite(num,i);
	}
	for(int i=0;i<Q;++i)
   {
   	  cin>>c1;
   	  scanf("%d",&num);
   	  if(c1=='M')
   	  {
   	  	Mark[num]=1;
	  }
	  else
	  {
	  	  int tmp=0;
	  	  while(Par[num]!=num)
	  	  {
	  	  	if(Mark[num])
	  	  	{
	  	  	  tmp=num;
			  break;	
			}
	  	  	num=Par[num];
		  }
	     if(tmp==0)
	        ans+=1;
		 else
		    ans+=tmp;
	  }
     }
     printf("%lld\n",ans);
  }
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3912
final_rank: 12