P6166 题解

P6166 题解

Overview

数据结构裸题,但如果不用数据结构?

Description

给定初始字符串 s 为空,需要进行如下操作:

  • 在字符串末尾加上任意字符 c c c
  • 给定下标 x x x,输出 s[x]
  • 撤销之前的 x x x 个指令,包括且仅包括 1 和 3 两种操作。

Solution

Solution #1

涉及到撤销操作,考虑使用主席树。

直接套模板。

Solution #2

注意到我主席树模板只有 24 分的好成绩,考虑使用别的方法。

注意到指令可以构成一棵树(Vim 和 Emacs 有一个 Undotree 插件,可以看看),考虑树上操作。
于是字符串长度为树的深度,树上倍增可以找到其祖先。

Code
#include 

using namespace std;

char dt[1000001];
int ind[1000001], dep[1000001];
int an[1000001][20], tot = 0, currd = 0;

void init_vars(){
	// type your initiating code...
}

void add(int pos, char x){
    int prev = ind[pos - 1];
    ind[pos] = ++tot;
    an[tot][0] = prev;
    dt[tot] = x;
    dep[tot] = dep[prev] + 1;
    for(int i = 1; i <= 20; i++)
        an[tot][i] = an[an[tot][i - 1]][i - 1];
    currd = dep[tot];
}
void rem(int pos, int x){
    ind[pos] = ind[pos - x - 1];
    currd = dep[ind[pos]];
}
char get(int x, int dep){
    int pos = ind[x];
    //cout << pos << "-(" << dep << ")>";
    for(int i = 20; i >= 0; i--){
        if(dep >= (1 << i))
            dep -= (1 << i), pos = an[pos][i];
    }
    //cout << pos << endl;
    return dt[pos];
}

void solve(int testcase, ...){
	init_vars();
    int n, st = 0; cin >> n;
    vector<char> ans;
    for(int i = 0; i <= 20; i++)
        an[1][i] = 1;
    for(int i = 1; i <= n; i++){
        char op;
        cin >> op;
        if(op == 'T'){
            char c; cin >> c;
            add(++st, c);
        }
        else if(op == 'U'){
            int x; cin >> x;
            rem(++st, x);
        }
        else{
            int x; cin >> x;
            ans.push_back(get(st, currd - x - 1));
        }
    }
    for(int i = 0; i < ans.size(); i++) cout << ans[i] << endl;
    cout << endl;
}

signed main(){
#ifdef files
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
    solve(1);
#ifdef files
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}

/*
 *  things to check
 *  1.  int overflow or long long memory need
 *  2.  recursion/array/binary search/dp/loop bounds
 *  3.  precision
 *  4.  special cases(n=1,bounds)
 *  5.  delete debug statements
 *  6.  initialize(especially multi-tests)
 *  7.  = or == , n or m ,++ or -- , i or j , > or >= , < or <=
 *  8.  keep it simple and stupid
 *  9.  do not delete, use // instead
 *  10. operator priority
 *  11. is there anything extra to output?
 *  12. THINK TWICE CODE ONCE, THINK ONCE DEBUG FOREVER
 *  13. submit ONCE, AC once. submit twice, WA forever
 *  14. calm down and you'll get good rank
 *  15. even a bit wrong scores zero
 *  16. ...
 **/

 /*
 *  something to think about
 *  1. greedy? dp? searching? dp with matrix/ segment tree? binary search? ...?
 *  2. If it is difficult, why not the opposite?
 **/

/*
   ##########   ############   #####         #####
 ####                 #####      ####       ####
####                 #####        ####     ####
####             ##########        ####   ####
####               #####              #####
####              #####               #####
 ####            #####                #####
   ###########  #############         #####
*/


你可能感兴趣的:(c++,算法)