HNOI 2010 bounce 弹飞绵羊

这道题用动态树实现还比较简单,这是我第一次写动态树,发现常数还是没有传说中的那么大,而且比较好写。

/* * $File: bounce.cpp * $Date: Fri Jul 09 17:30:49 2010 +0800 */ #define INPUT "bounce.in" #define OUTPUT "bounce.out" #include #include namespace Solve { const int NVTX_MAX = 200005; struct Tree_node { int dpar, par; }; Tree_node tree[NVTX_MAX]; namespace Splay { struct Node { int par, size, ch[2]; }; Node tree[NVTX_MAX]; int tree_root; int &get_ref(int x) { int par = tree[x].par; if (!par) { tree_root = x; return tree_root; } return tree[par].ch[x == tree[par].ch[1]]; } void rotate(int &root, int dir); void splay(int root); int get_index(int root); int get_head(int root) __attribute__((fastcall)); int split(int root); // split root and the node right after it // in the inorder traversal, return that node void concatenate(int v0, int v1); // make v1 the successor of v0 } void expose(int v0); void cut(int v0); void link(int v0, int v1); // make v1 the parent of v0 int query_depth(int v0); void modify_par(int v0, int tpar); void solve(FILE *fin, FILE *fout); } void Solve::solve(FILE *fin, FILE *fout) { int n, root; fscanf(fin, "%d", &n); root = n + 1; for (int i = 1; i <= n; i ++) { int k; fscanf(fin, "%d", &k); k += i; if (k > root) k = root; tree[i].par = k; Splay::tree[i].size = 1; } Splay::tree[root].size = 1; int m; fscanf(fin, "%d", &m); while (m --) { int i, j; fscanf(fin, "%d%d", &i, &j); j ++; if (i == 1) fprintf(fout, "%d/n", query_depth(j)); else { int k; fscanf(fin, "%d", &k); k += j; if (k > root) k = root; modify_par(j, k); } } } void Solve::modify_par(int v0, int tpar) { cut(v0); link(v0, tpar); } void Solve::cut(int v0) { if (tree[v0].dpar) Splay::split(tree[v0].par); tree[v0].dpar = tree[v0].par = 0; /* expose(v0); assert(tree[v0].dpar == tree[v0].par); Splay::split(tree[v0].par); tree[v0].par = tree[v0].dpar = 0; */ } void Solve::link(int v0, int v1) { assert(!tree[v0].par); tree[v0].par = v1; tree[v0].dpar = 0; /* assert(!tree[v0].par); expose(v1); tree[v0].par = tree[v0].dpar = v1; Splay::concatenate(v1, v0); */ } int Solve::query_depth(int v0) { expose(v0); return Splay::get_index(v0); } void Solve::expose(int v0) { while (1) { int head = Splay::get_head(v0); if (tree[head].par) { assert(!tree[head].dpar); int p = tree[head].par; tree[Splay::split(p)].dpar = 0; tree[head].dpar = p; Splay::concatenate(p, head); v0 = p; } else return; } } void Solve::Splay::rotate(int &root, int dir) { int ch = tree[root].ch[!dir]; tree[ch].par = tree[root].par; tree[ch].size = tree[root].size; tree[ tree[root].ch[!dir] = tree[ch].ch[dir] ].par = root; tree[root].size = tree[tree[root].ch[0]].size + tree[tree[root].ch[1]].size + 1; tree[ tree[ch].ch[dir] = root ].par = ch; root = ch; } void Solve::Splay::splay(int root) { while (tree[root].par) { int par = tree[root].par, parpar = tree[par].par, d = (root == tree[par].ch[0]); if (!parpar) { rotate(get_ref(par), d); return; } if (d ^ (par == tree[parpar].ch[0])) { rotate(get_ref(par), d); rotate(get_ref(parpar), !d); } else { int &r = get_ref(parpar); rotate(r, d); rotate(r, d); } } } int Solve::Splay::get_index(int root) { splay(root); return tree[tree[root].ch[0]].size; } int Solve::Splay::get_head(int root) { while (tree[root].par) root = tree[root].par; while (tree[root].ch[0]) root = tree[root].ch[0]; return root; } int Solve::Splay::split(int root) { splay(root); int ret = tree[root].ch[1]; tree[root].size -= tree[ret].size; tree[root].ch[1] = 0; tree[ret].par = 0; while (tree[ret].ch[0]) ret = tree[ret].ch[0]; splay(ret); return ret; } void Solve::Splay::concatenate(int v0, int v1) { splay(v1); assert(!tree[v1].ch[0]); splay(v0); assert(!tree[v0].ch[1]); tree[v0].ch[1] = v1; tree[v0].size += tree[v1].size; tree[v1].par = v0; } int main() { #ifdef STDIO Solve::solve(stdin, stdout); #else FILE *fin = fopen(INPUT, "r"), *fout = fopen(OUTPUT, "w"); Solve::solve(fin, fout); fclose(fin); fclose(fout); #endif }

 

Problem: bounce
    Point    Execution Status     Score         Time [sec]    Memory [kb] 
    1        Normal               10.000        0.043         2568        
    2        Normal               10.000        0.541         4680        
    3        Normal               10.000        0.024         2564        
    4        Normal               10.000        0.359         4212        
    5        Normal               10.000        0.329         3548        
    6        Normal               10.000        0.411         4388        
    7        Normal               10.000        0.317         3744        
    8        Normal               10.000        0.311         4612        
    9        Normal               10.000        0.343         6732        
    10       Normal               10.000        0.396         7012        

你可能感兴趣的:(HNOI 2010 bounce 弹飞绵羊)