zoukankan      html  css  js  c++  java
  • 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


    解题心得:

    1. 题意就是有一棵树,有两种操作,第一种是将某个点标记,第二种是询问距离某个点被标记的最进的祖先节点的编号,最后需要你打印出所有询问编号的总和。
    2. 据说这题每次回溯跑暴力都能跑出来,因为时间给了八秒嘛,其实我感觉这是考了一个并查集关于树的变形
      这里写图片描述这样改变了树的深度,在询问答案的时候就可以O(1)得到答案,那怎么改变树的的形态呢。
    3. 其实可以将树的每个结点看成一颗新的树,每次标记的时候就可以将这个标记的节点看成根节点,形成一个子树,然后将它下面没有出现子树的部分全部合并起来。

    #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
    ",sum);
    }
    
    int main() {
        while(scanf("%d%d",&n,&m) && n|m) {
            init();
            Solve();
        }
        return 0;
    }
  • 相关阅读:
    软件工程小组问世第八章之测试文档
    软件工程小组问世第六章之概要设计白银篇
    软件工程小组问世第六章之概要设计青铜篇
    小组会谈(2019.5.15)
    小组会谈(2019.4.19)
    小组会谈(2019.4.12)
    小组会谈(2019.4.30)
    软件工程小组问世第五章之需求规格说明书白银篇
    HanLP封装为web services服务的过程介绍
    hanlp分词工具应用案例:商品图自动推荐功能的应用
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9107137.html
Copyright © 2011-2022 走看看