【动态树】uva11994 Happy Painting!

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3145

给一个森林,每条边有一种颜色,有3种操作,A、将以x于其父亲断开并连到y上;B、将x到y路上的边染成颜色c;C、询问x到y的路的长度以及路上有多少种颜色。

比较赤裸的动态树问题,强烈推荐杨哲的《QTREE解法的一些研究》,其上对于link_cut tree 的介绍通俗易懂。

这里我稍微讲一下题目中要注意的地方,其中这里每条边都有自己独立的属性,颜色。而标准的link_cut tree.中的节点表示的树上的点,对于边的属性放在哪个点上这里要非常非常仔细的考虑!一开始我想当然的以为两个端点中低的那个点=。=~结果可想而知。。这里我下一个详尽的定义:对于splay上的节点,其记录的边是以其为根的splay子树,与这条链(一整棵splay树是实际中的一条链)其他部分链接的边。。这里再次强烈建议Rotate的时候,画图把边标上号,弄清楚边的转移。

其次,对于Link_cut tree中的虚边,可以借用splay tree的*fa存在即可。

恩,从此我也有动态树模板拉~

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stack>
  6 #define X first
  7 #define Y second
  8 #define mp(x,y) make_pair(x,y)
  9 #define Rep(i,n) for(int i = 0; i<n; i++)
 10 using namespace std;
 11 typedef pair<int,int> pii;
 12 
 13 #define    N 100015
 14 int        n,m;
 15 struct    Splaynode{
 16     Splaynode *fa,*ch[2];
 17     int        key,c,mark,size,id;
 18     bool    rev;
 19     void    updata(){
 20         key = 0;
 21         size = 1;
 22         Rep(i,2) if ( ch[i] )
 23             key |= ch[i]->key | (1<<ch[i]->c) , 
 24             size += ch[i]->size;
 25     }
 26     void    down(){
 27         if ( mark ){
 28             if ( ch[0] ) {
 29                 ch[0]->c = ch[0]->mark = mark; 
 30                 ch[0]->key = key;
 31             }
 32             if ( ch[1] ) {
 33                 ch[1]->c = ch[1]->mark = mark; 
 34                 ch[1]->key = key;
 35             }
 36             mark = 0;
 37         }
 38         if ( rev ){
 39             if ( ch[0] ) ch[0]->rev ^= 1; 
 40             if ( ch[1] ) ch[1]->rev ^= 1; 
 41             swap( ch[0] , ch[1] );
 42         }
 43         rev = false;
 44     }
 45 }node[N];
 46 
 47 struct    LCT{
 48     void     Rotate( Splaynode *x ) {
 49         Splaynode *y = x->fa;
 50         int col = y->c;
 51         int    d = y->ch[1] == x;
 52         if ( x->fa = y->fa ) {
 53             if ( y->fa->ch[0] == y ) y->fa->ch[0] = x;
 54             if ( y->fa->ch[1] == y ) y->fa->ch[1] = x;
 55         }
 56         if ( y->ch[d] = x->ch[d^1] ) {
 57             y->ch[d]->fa = y;
 58             y->c = y->ch[d]->c;
 59             y->ch[d]->c = x->c;
 60             x->c = col;
 61         }
 62         else swap(x->c,y->c);
 63         x->ch[d^1] = y;
 64         y->fa = x;
 65         y->updata();
 66         x->updata();
 67     }
 68     inline bool    is_root( Splaynode *u ){
 69         if ( !u->fa ) return true;
 70         return (u->fa->ch[0]!=u && u->fa->ch[1]!=u );
 71     }
 72     void    Splay( Splaynode *x ){
 73         stack<Splaynode*> g;
 74         Splaynode *tmp = x;
 75         while ( true ){
 76             g.push( tmp );
 77             if ( is_root(tmp) ) break;
 78             tmp = tmp->fa;
 79         }
 80         while ( !g.empty() ){
 81             g.top()->down();
 82             g.pop();
 83         }
 84         while ( !is_root(x) ){
 85             if ( is_root(x->fa) ) Rotate(x);
 86             else {
 87                 int d1 = x->fa->fa->ch[1] == x->fa,
 88                     d2 = x->fa->ch[1] == x;
 89                 if ( d1 == d2 ) Rotate(x->fa),Rotate(x);
 90                 else Rotate(x),Rotate(x);
 91             }
 92         }
 93     }
 94     void    Access( Splaynode* u ){
 95         Splaynode *v = NULL;
 96         for (; u; u = u->fa ){
 97             Splay(u);
 98             u->ch[1] = v;
 99             (v=u)->updata();
100         }
101     }
102     void    Cut( Splaynode* u ) {
103         Access(u);
104         Splay(u);
105         if ( u->ch[0] ) {
106             u->ch[0]->fa = NULL;
107             u->ch[0]->c  = 0;
108         }
109         u->ch[0] = NULL;
110     }
111     void    Link( Splaynode *u, Splaynode *v ,int col ) {
112         Access(v);
113         Splay(u);
114         Splaynode *tmp = u;
115         while ( !is_root(tmp) ) tmp = tmp->fa;
116         if ( tmp == v ) return;
117         Cut(u);
118         u->fa = v;
119         u->c = col;
120     }
121     Splaynode*    GetRoot( Splaynode* u){
122         Access(u);
123         Splay(u);
124         Splaynode* ret = u;
125         while ( ret->ch[0] ) ret = ret->ch[0];
126         Splay(ret);
127         return ret;
128     }
129     void    MakeRoot( Splaynode* u){
130         Access(u);
131         Splay(u);
132         u->rev ^= 1; 
133     }
134     void    Set( Splaynode *u , Splaynode *v ,int col ) {
135         Splaynode *root = GetRoot(u);
136         if ( root != GetRoot(v) ) return;
137         MakeRoot(u);
138         Access(v);
139         Splay(v);
140         v->mark = col;
141         v->key = 1<<col;
142         MakeRoot(root);
143     }
144     pii        Ask( Splaynode *u , Splaynode *v ) {
145         Splaynode *root = GetRoot(u);
146         if ( root != GetRoot(v) ) return mp(0,0);
147         MakeRoot(u);
148         Access(v);
149         Splay(v);
150         int k = v->key; 
151         pii    ret(v->size-1,0);
152         while ( k ) { ret.Y += k&1; k >>= 1; }
153         MakeRoot(root);
154         return ret;
155     }
156 }tree;
157 
158 int        main(){
159     int    kind,u,v,col;
160     pii    ans;
161     while ( ~scanf("%d%d", &n, &m ) ) {
162         memset( node , 0 , sizeof(node) );
163         for (int i = 1; i<=n; i++) {
164             scanf("%d", &u );
165             if ( u ) node[i].fa = &node[u];
166             node[i].id = i;
167         }
168         for (int i = 1; i<=n; i++) {
169             scanf("%d", &u );
170             if ( node[i].fa ) node[i].c = u;
171         }
172         while ( m -- ) {
173             scanf("%d", &kind );
174             switch    ( kind ) {
175                 case 1:
176                     scanf("%d%d%d", &u, &v, &col );
177                     tree.Link( &node[u] , &node[v], col );
178                     break;
179                 case 2:
180                     scanf("%d%d%d", &u, &v, &col );
181                     tree.Set( &node[u] , &node[v], col );
182                     break;
183                 default:
184                     scanf("%d%d", &u, &v );
185                     ans = tree.Ask( &node[u], &node[v] );
186                     printf("%d %d\n" , ans.X , ans.Y );
187             }
188         }
189     }
190     return 0;
191 }

 

posted @ 2013-02-24 03:12  lzqxh  阅读(338)  评论(0编辑  收藏  举报