【OI】操做樹

操做數,通常用來作那些對數列進行添加、撤銷操做的題。node

 

假設一開始有一個空數列,有三個操做ios

(1)在數列後加一個數ide

(2)求數列中某位置的值測試

(3)撤銷掉最後進行的若干次操做(1和3)spa

 

考慮建一棵樹,1操做則爲在當前節點下新加一個節點,2操做求數列k位置值,則爲從根節點到當前節點k個節點的位置的節點code

3操做撤銷掉最後進行的k次操做則爲回溯k個節點,同時記錄回溯前的當前節點和回溯後的當前節點。blog

因此每次進行查詢的時候,先從當前節點找父親,一直找到根節點,記錄節點個數,而後節點個數-k獲得當前節點到要查詢的節點的距離。內存

撤銷操做的時候,父親是1操做的節點就往上找父親,父親是3操做節點就跳到那個3操做回溯以前的那個「當前節點」ci

 

例如這道題:io

總時間限制: 
10000ms
 
單個測試點時間限制: 
1000ms
 
內存限制: 
262144kB
描述

給一個空數列,有M次操做,每次操做是如下三種之一:

(1)在數列後加一個數

(2)求數列中某位置的值

(3)撤銷掉最後進行的若干次操做(1和3)

輸入
第一行一個正整數M。
接下來M行,每行開頭是一個字符,若該字符爲'A',則表示一個加數操做,接下來一個整數x,表示在數列後加一個整數x;若該字符爲'Q',則表示一個詢問操做,接下來一個整數x,表示求x位置的值;若該字符爲'U',則表示一個撤銷操做,接下來一個整數x,表示撤銷掉最後進行的若干次操做。
輸出
對每個詢問操做單獨輸出一行,表示答案。
樣例輸入
9
A 1
A 2
A 3
Q 3
U 1
A 4
Q 3
U 2
Q 3
樣例輸出
3
4
3
提示
1<=M<=10^5,輸入保證合法,且全部整數可用帶符號32位整型存儲。
#include <cstdio>
#include <iostream>

const int MaxN = 100001;
int fa[MaxN];
//bool edge[MaxN][MaxN];
int n;
int V[MaxN];
int back[MaxN];

int main()
{
    scanf("%d",&n);
    
    int now_node;
    
    char XX;
    std::cin>>XX;
    int xx;
    scanf("%d",&xx);
    now_node = 1;
    
    int node_cnt = 1;
    V[node_cnt] = xx;
    
    for(int l = 2; l <= n; l++){
        char X;
        std::cin>>X;
        if(X == 'A'){
            int nx;
            scanf("%d",&nx);
            V[++node_cnt] = nx;
            fa[node_cnt] = now_node;
            //edge[now_node][node_cnt] = 1;
            now_node = node_cnt;
            
        }
        else if(X == 'U'){
            int nx;
            scanf("%d",&nx);
            int last_node = now_node;
            for(int i = 1; i <= nx; i++){
                if(!back[now_node])
                    now_node = fa[now_node];
                else
                    now_node = back[now_node];
                
            }
            back[now_node] = last_node;
            
        }
        else if(X == 'Q'){
            int nx;
            scanf("%d",&nx);
            
            int count = 0;
            int tmp = now_node;
            while(1){
                if(!fa[tmp]){
                    break;
                }
                tmp = fa[tmp];
                count++;
            }
            count = count - nx;
            tmp = now_node;
            for(int i = 1; i <= count; i++){
                tmp = fa[tmp];
            }
            printf("%d\n",V[tmp]);
        }
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索