【tree】spoj QTREE系列

学了LCT之后,貌似听说QTREE系列有这方面题,做完发现原来都是树分治方面的题,=。=~

www.spoj.com/problems/QTREE

www.spoj.com/problems/QTREE1

www.spoj.com/problems/QTREE2

www.spoj.com/problems/QTREE3

www.spoj.com/problems/QTREE4

QTREE1:最基本的树链剖分=。=

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<map>
  5 #include<cctype>
  6 #include<algorithm>
  7 #define N 10010
  8 #define Rep(i,n) for(int i = 0; i<n; i++) 
  9 using namespace std;
 10 int        ecnt;
 11 struct    Edge{
 12     int to,w;
 13     Edge *next;
 14 }*mat[N],edges[N*2];
 15 void    link(int x,int to,int w){
 16     edges[ecnt].to = to;
 17     edges[ecnt].w = w;
 18     edges[ecnt].next = mat[x];
 19     mat[x] = &edges[ecnt++];
 20 }
 21 
 22 int        n,val[N];
 23 int        size[N],son[N],fa[N],dev[N],num[N];
 24 int        in_tree[N],cnt,w[N],top[N],h[N];
 25 void    dfs1(int x,int father){
 26     size[x] = 1;
 27     son[x] = -1;
 28     for ( Edge *p = mat[x]; p ; p = p->next ){
 29         int to = p->to;
 30         if ( to == father ) continue;
 31         dev[to] = dev[x]+1;
 32         fa[to] = x;
 33         num[to] = val[p->w];
 34         h[p->w] = to;
 35         dfs1(to,x);
 36         if ( son[x] == -1 || size[to] > size[son[x]] ) son[x] = to;
 37         size[x] += size[to];
 38     }
 39 }
 40 
 41 void    dfs2(int x,int father,int tp){
 42     w[in_tree[x] = ++cnt] = num[x];
 43     top[x] = tp;
 44     if ( son[x] == -1 ) return;
 45     dfs2(son[x],x,tp);
 46     for ( Edge *p = mat[x]; p ; p = p->next ){
 47         int to = p->to;
 48         if ( to == father || to == son[x] ) continue;
 49         dfs2(to,x,to);
 50     }
 51 }
 52 
 53 struct    Segtree{
 54     int left[N*4], right[N*4],key[N*4];
 55     void    build(int l,int r ,int step ){
 56         left[step] = l , right[step] = r;
 57         if ( l == r ) { key[step] = w[l]; return; }
 58         int mid = (l+r)>>1;
 59         build( l , mid , step*2 );
 60         build( mid+1, r , step*2+1 );
 61         key[step] = max( key[step*2] , key[step*2+1] );
 62     }
 63     void    updata( int w ,int val,int step ){
 64         if ( left[step] == right[step] ) { key[step] = val; return; }
 65         int mid = (left[step]+right[step])/2;
 66         if ( w <= mid ) updata( w , val, step*2 );
 67         else updata( w ,val, step*2+1 );
 68         key[step] = max( key[step*2] , key[step*2+1] );
 69     }
 70     int        ask(int l,int r,int step ){
 71         if ( left[step] == l && r == right[step] ) return key[step];
 72         int mid = (left[step]+right[step])/2;
 73         if ( r<=mid ) return ask(l,r,step*2);
 74         else if ( l > mid ) return ask(l,r,step*2+1);
 75         else return max( ask(l,mid,step*2), ask(mid+1,r,step*2+1) );
 76     }
 77 }tree;
 78 
 79 int        next_char(){
 80     char ch = getchar();
 81     while ( !isupper(ch) ) ch = getchar();
 82     int ret = ch == 'D'?0:(ch=='C'?1:2);
 83     while ( isupper(ch) ) ch = getchar();
 84     return ret;
 85 }
 86 int        next_int(){
 87     int    ret = 0; 
 88     char ch = getchar();
 89     while ( !isdigit(ch) ) ch = getchar();
 90     while ( isdigit(ch) ) {
 91         ret = ret * 10 + ch-'0';
 92         ch = getchar();
 93     }
 94     return ret;
 95 }
 96 int        main(){
 97     int cas,x,y;
 98     char str[20];
 99     scanf("%d", &cas );
100     while ( cas -- ) {
101         ecnt = cnt = 0; 
102         memset( mat , 0 , sizeof(mat) );
103         scanf("%d", &n );
104         Rep(i,n-1) {
105             scanf("%d%d%d", &x, &y, &val[i] );
106             link(x ,y , i);
107             link(y ,x , i);
108         }
109         dfs1(1,-1);
110         dfs2(1,-1,1);
111         tree.build(1,n,1);
112         int    kind;
113         while ( kind = next_char() ) {
114             if ( kind == 0 ) break;
115             x = next_int();
116             y = next_int();
117             if ( kind == 1 ) tree.updata( in_tree[h[x-1]] , y , 1 );
118             else {
119                 int u = x, v = y, ans = 1<<31 ;
120                 while ( top[u] != top[v] ){
121                     if ( dev[top[u]] < dev[top[v]] ) swap(u,v);
122                     ans = max( ans , tree.ask(in_tree[top[u]] , in_tree[u] , 1) );
123                     u = fa[top[u]];
124                 }
125                 if ( dev[v] < dev[u] ) swap(u,v);
126                 if ( u != v ) ans = max( ans , tree.ask(in_tree[u]+1,in_tree[v],1) );
127                 printf("%d\n" , ans );
128             }
129         }
130     }
131 }

 

QTREE2:求两个点之间距离,求两点之间第k点。。树链剖分也可以,不过简单跳表就足够了,复杂度都是O(nlogn)

View Code
 1 //By Lin
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<map>
 5 #include<cctype>
 6 #include<algorithm>
 7 #define N 10010
 8 #define Rep(i,n) for(int i = 0; i<n; i++) 
 9 using namespace std;
10 int        ecnt;
11 struct    Edge{
12     int to,w;
13     Edge *next;
14 }*mat[N],edges[N*2];
15 void    link(int x,int to,int w){
16     edges[ecnt].to = to;
17     edges[ecnt].w = w;
18     edges[ecnt].next = mat[x];
19     mat[x] = &edges[ecnt++];
20 }
21 
22 int        n;
23 int        dev[N],dis[N];
24 int        fa[N][20];
25 
26 void    dfs(int x,int father){
27     for ( Edge *p = mat[x];p ; p =p->next ){
28         int to = p->to;
29         if ( to == father ) continue;
30         dev[to] = dev[x]+1;
31         dis[to] = dis[x]+p->w;
32         fa[to][0] = x;
33         for (int i = 1; (1<<i)<=dev[to]; i++)
34             fa[to][i] = fa[fa[to][i-1]][i-1];
35         dfs(to,x);
36     }
37 }
38 int        root(int x,int lev){
39     for (int i = 0; lev ; i = i+1 ){
40         if ( lev&1 ) x = fa[x][i];
41         lev >>= 1;
42     }
43     return x;
44 }
45 
46 int        lca(int u,int v){
47     if ( dev[u] < dev[v] ) swap(u,v);
48     u = root(u,dev[u]-dev[v]);
49     if ( u == v ) return u;
50     for (int i = 20; i>=0; i--){
51         if ( (1<<i)>dev[u] ) continue;
52         if ( fa[u][i] != fa[v][i] )
53             u = fa[u][i] , v = fa[v][i];
54     }
55     return fa[u][0];
56 }
57 int        main(){
58     int cas,x,y,w;
59     char str[20];
60     scanf("%d", &cas );
61     while ( cas -- ) {
62         ecnt = 0;
63         memset( mat , 0 , sizeof(mat) );
64         scanf("%d", &n );
65         Rep(i,n-1) {
66             int w;
67             scanf("%d%d%d", &x, &y, &w );
68             link(x ,y , w);
69             link(y ,x , w);
70         }
71         dfs(1,-1);
72         while ( scanf("%s", str ) ) {
73             if ( strcmp(str,"DONE") == 0 ) break;
74             scanf("%d%d", &x, &y );
75             if ( str[0] == 'D' ) printf("%d\n" , dis[x]+dis[y]-2*dis[lca(x,y)] );
76             else {
77                 int k;
78                 scanf("%d", &k );
79                 k--;
80                 int u = x, v = y, w = lca(x,y);
81                 if ( dev[u]-dev[w] >= k ) printf("%d\n" , root(u,k) );
82                 else printf("%d\n", root(v,dev[u]+dev[v]-2*dev[w]-k ) );
83             }
84         }
85         puts("");
86     }
87 }

 

QTREE3: 把某个点的颜色从黑变成白,或者从白变成黑。。求从1到v路径上第1个黑色节点。。树链剖分,从v往上走,logn条链,利用线段树找每条链第一个黑色点。。同QTREE2,也可以用跳表搞

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cctype>
  5 #define N 100100
  6 #define Rep(i,n) for(int i = 0; i<(n); i++)
  7 using namespace std;
  8 
  9 int        ecnt;
 10 struct    Edge{
 11     int to;
 12     Edge *next;
 13 }*mat[N],edges[N*2];
 14 void    link(int x,int to){
 15     edges[ecnt].to = to;
 16     edges[ecnt].next = mat[x];
 17     mat[x] = &edges[ecnt++];
 18 }
 19 
 20 int        n,m;
 21 int        dev[N],in_tree[N],col[N],cnt;
 22 int        size[N],son[N],fa[N],tp[N],id[N];
 23 void    dfs1(int x,int father){
 24     size[x] = 1;
 25     son[x] = -1;
 26     for( Edge *p = mat[x]; p ; p = p->next ){
 27         int to = p->to;
 28         if ( to == father ) continue;
 29         fa[to] = x;
 30         dfs1(to,x);
 31         if ( son[x] == -1 || size[to] > size[son[x]] ) son[x] = to;
 32         size[x] += size[to];
 33     }
 34 }
 35 void    dfs2(int x,int father,int top){
 36     id[ in_tree[x] = ++cnt ] = x;
 37     tp[x] = top;
 38     if ( son[x] == -1 ) return;
 39     dfs2(son[x],x,top);
 40     for( Edge *p = mat[x]; p ; p = p->next ){
 41         int to = p->to;
 42         if ( to == father || to == son[x] ) continue;
 43         dfs2(to,x,to);
 44     }
 45 }
 46 
 47 struct    Segtree{
 48     int left[N*4],right[N*4],key[N*4];
 49     void    build(int l,int r,int step){
 50         left[step] = l , right[step] = r , key[step] = -1;
 51         if ( l == r ) return;
 52         int mid = ( l+r) /2;
 53         build( l , mid , step*2 );
 54         build(mid+1, r , step*2+1 );
 55     }
 56     void    updata(int w,int step ){
 57         if ( left[step] == right[step] ) {
 58             key[step ] = key[step]==-1?id[w]:-1;
 59             return;
 60         }
 61         int mid = ( left[step] + right[step] )/2;
 62         updata( w , step*2+(w>mid) );
 63         key[step] = key[ step*2+(key[step*2] == -1) ];
 64     }
 65     int        ask(int l,int r,int step){
 66         if ( left[step] == l && right[step] == r ) return key[step];
 67         int mid = ( left[step] + right[step] )/2;
 68         if ( r <= mid ) return ask(l,r,step*2);
 69         else if ( l > mid ) return ask(l,r,step*2+1);
 70         else {
 71             int ret = ask(l,mid,step*2);
 72             return ret == -1 ? ask(mid+1,r,step*2+1):ret;
 73         }
 74     }
 75 }tree;
 76 
 77 char    ch;
 78 int        next_int(){
 79     int    ret = 0; 
 80     ch = getchar();
 81     while ( !isdigit(ch) ) ch = getchar();
 82     while ( isdigit(ch) ) { ret = ret*10+ch-'0'; ch = getchar(); }
 83     return ret;
 84 }
 85 int        main(){
 86     int x,y,kind,v;
 87     n = next_int();
 88     m = next_int();
 89     Rep(i,n-1){
 90         x = next_int();
 91         y = next_int();
 92         link(x,y);
 93         link(y,x);
 94     }
 95     dfs1(1,-1);
 96     dfs2(1,-1,1);
 97     tree.build(1,n,1);
 98     while ( m -- ) {
 99         kind = next_int();
100         v = next_int();
101         if ( kind ){
102             int ans = -1;
103             while ( v ){
104                 int k = tree.ask( in_tree[tp[v]], in_tree[v] , 1 );
105                 ans = k==-1?ans:k;
106                 v = fa[tp[v]];
107             }
108             printf("%d\n" , ans );
109         }
110         else tree.updata( in_tree[v] , 1 );
111     }
112     return 0;
113 }

 

QTREE4:把某个点的颜色从黑变成白,或者从白变成黑。。求整棵树距离最远的2个黑色点间距离。。这里我的程序用了点分治,复杂度为O(nlogn^2)。。但是每次修改要经过3层堆,效率极度底下。。。极限数据单组要跑4.0s+...。正解可以参考漆子超的论文《分治算法在树上的应用》,其介绍了用树链剖分+线段树的方法。。或者也可以用边分治,由于每次将树分成2个块,而不是点分治的n个块,又可以减少一层堆的应用,同样可以参考漆子超的论文来避免边分治的退化情况。。。在网上找到的树链剖分+线段树的标程通用复杂度效率足足是我程序的10倍!!!。。STL用多了跟OI出生的选手没法比啊。

**改程序提交结果为TLE,但是经过对拍验证过其正确性

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cctype>
  5 #include<map>
  6 #include<algorithm>
  7 #include<set>
  8 #include<vector>
  9 #define X first
 10 #define Y second
 11 #define mp(x,y) make_pair(x,y)
 12 #define Rep(i,n) for(int i = 0; i<n; i++)
 13 #define foreach(it,n) for( __typeof(n.begin()) it = n.begin(); it!=n.end(); it++)
 14 #define N 100010
 15 using namespace std;
 16 typedef pair<int,int> pii;
 17 
 18 struct    SBTNode{
 19     int lc,rc,key,sz;
 20 }SBTtree[N*20];
 21 int        keep[N*20],end,top; 
 22 
 23 void    RightRotate(int &root )
 24 {
 25     int y = SBTtree[root].lc;
 26     SBTtree[root].lc = SBTtree[y].rc; 
 27     SBTtree[y].rc = root; 
 28     SBTtree[y].sz = SBTtree[root].sz; 
 29     SBTtree[root].sz = SBTtree[SBTtree[root].lc].sz + SBTtree[SBTtree[root].rc].sz+1; 
 30     root = y; 
 31 }
 32 
 33 void    LeftRotate(int &root )
 34 {
 35     int y = SBTtree[root].rc; 
 36     SBTtree[root].rc = SBTtree[y].lc; 
 37     SBTtree[y].lc = root; 
 38     SBTtree[y].sz = SBTtree[root].sz; 
 39     SBTtree[root].sz = SBTtree[SBTtree[root].lc].sz + SBTtree[SBTtree[root].rc].sz+1; 
 40     root = y; 
 41 }
 42 
 43 void    Maintain( int &root , bool flag ) 
 44 {
 45     if ( !flag ) {
 46         if ( SBTtree[SBTtree[SBTtree[root].lc].lc].sz > SBTtree[SBTtree[root].rc].sz ) RightRotate( root ); 
 47         else if ( SBTtree[SBTtree[SBTtree[root].lc].rc].sz > SBTtree[SBTtree[root].rc].sz ){
 48             LeftRotate( SBTtree[root].lc ); 
 49             RightRotate( root ); 
 50         }
 51         else return; 
 52     }
 53     else{
 54         if ( SBTtree[SBTtree[SBTtree[root].rc].rc].sz > SBTtree[SBTtree[root].lc].sz ) LeftRotate( root ); 
 55         else if ( SBTtree[SBTtree[SBTtree[root].rc].lc].sz > SBTtree[SBTtree[root].lc].sz ){
 56             RightRotate( SBTtree[root].rc ); 
 57             LeftRotate( root ); 
 58         }
 59         else return; 
 60     }
 61     Maintain( SBTtree[root].lc , false );
 62     Maintain( SBTtree[root].rc , true );
 63     Maintain( root , false );
 64     Maintain( root , true );
 65     
 66 }
 67 
 68 void    SBTInsert( int &root , int key ){
 69     if ( root == 0 ) {
 70         if ( end ) root = keep[--end]; 
 71         else root = ++top; 
 72         SBTtree[root].key = key; 
 73         SBTtree[root].sz = 1; 
 74         SBTtree[root].lc = SBTtree[root].rc = 0; 
 75         return; 
 76     }
 77     SBTtree[root].sz ++; 
 78     if ( SBTtree[root].key > key ) SBTInsert( SBTtree[root].lc , key ); 
 79     else SBTInsert( SBTtree[root].rc , key ); 
 80     Maintain( root , SBTtree[root].key >= key ); 
 81 }
 82 
 83 int        SBTDel(int &root ,int key ) 
 84 {
 85     int ret; 
 86     SBTtree[root].sz --;
 87     if ( key < SBTtree[root].key && SBTtree[root].lc ) ret = SBTDel( SBTtree[root].lc , key ); 
 88     else if ( key > SBTtree[root].key && SBTtree[root].rc ) ret = SBTDel( SBTtree[root].rc , key ); 
 89     else 
 90     {
 91         if ( !SBTtree[root].lc || !SBTtree[root].rc ) {
 92             keep[end++] = root; 
 93             root = SBTtree[root].lc + SBTtree[root].rc; 
 94             return SBTtree[keep[end-1]].key; 
 95         }
 96         ret = key; 
 97         SBTtree[root].key = SBTDel( SBTtree[root].lc , key+1 );
 98     }
 99     Maintain( root , key > ret ); 
100     return ret; 
101 }
102 int        SBTAsk(int &root) {
103     if ( root == 0 ) return -1000000000;
104     if ( SBTtree[root].rc ) return SBTAsk( SBTtree[root].rc);
105     return SBTtree[root].key;
106 }
107 
108 int        ecnt;
109 struct    Edge{
110     int to,w,k;
111     Edge *next;
112 }*mat[N],*fa[N],edges[N*20];
113 void    link( Edge *&k ,int to,int w,int kk = 0 ){
114     edges[ecnt].to = to;
115     edges[ecnt].w = w;
116     edges[ecnt].k = kk;
117     edges[ecnt].next = k;
118     k = &edges[ecnt++];
119 }
120 
121 int        n,m;
122 bool    mark[N];
123 int        last[N];
124 multiset<int> ans,ss[N];
125 int        tree[N*30],ncnt;
126 
127 int        Findroot(int x,int father,int &root,int &now,int tol){
128     int    size = 1, msize = 0; 
129     for ( Edge *p = mat[x]; p; p = p->next ){
130         int to = p->to;
131         if ( mark[to] || to == father ) continue;
132         int k = Findroot(to,x,root,now,tol);
133         msize = max( msize , k );
134         size += k;
135     }
136     msize = max( msize , tol-size );
137     if ( now == -1 || msize < now ) 
138         root = x , now = msize;
139     return size;
140 }
141 
142 int        dfs(int x,int father,int root,int L, int belong){
143     SBTInsert(tree[belong],L);
144     link( fa[x] , root , L , belong);
145     int    size = 1;
146     for ( Edge *p = mat[x]; p; p = p->next ){
147         int to = p->to;
148         if ( mark[to] || to == father ) continue;
149         size += dfs(to,x,root,L+p->w,belong);
150     }
151     return size;
152 }
153 
154 void    solve(int x,int tol){
155     int root , k = -1;
156     Findroot(x,-1,root,k,tol);
157     mark[root] = true;
158     link( fa[root] , root , 0 , ncnt );
159     SBTInsert( tree[ncnt] , 0 );
160     ncnt++;
161     ss[root].insert( 0 );
162     for ( Edge *p = mat[root]; p; p = p->next , k++ ){
163         int to = p->to;
164         if ( mark[to] ) continue;
165         k = ncnt;
166         solve( to , dfs(to,root,root,p->w,ncnt++) );
167         ss[root].insert( SBTAsk(tree[k]) );
168     }
169 }
170 int        get( const multiset<int> &ss ){
171     if ( ss.size()<2 ) return -1;
172     multiset<int>::iterator it = ss.end();
173     it--;
174     int k = *it;
175     it--;
176     k += *it;
177     return k;
178 }
179 
180 int        Nextint(){
181     int    ret = 0; 
182     char ch = getchar();
183     bool flag = false;
184     while ( !isdigit(ch) ) {
185         if ( ch == '-' ) flag = true;
186         ch = getchar();
187     }
188     while ( isdigit(ch) ){
189         ret = ret*10+ch-'0';
190         ch = getchar();
191     }
192     return flag?ret*-1:ret;
193 }
194 
195 int        main(){
196     int x,y,w;
197     n = Nextint();
198     Rep(i,n-1){
199         x = Nextint();
200         y = Nextint();
201         w = Nextint();
202         link( mat[x], y , w );
203         link( mat[y], x , w );
204     }
205     solve(1,n);
206     for (int i = 1; i<=n; i++){
207         if ( (last[i] = get(ss[i])) > 0 ) ans.insert( last[i] );
208     }
209     int num = n;
210     scanf("%d", &m );
211     ans.insert(0);
212     while ( m -- ) {
213         char    ch = getchar();
214         while ( !isupper(ch) ) ch = getchar();
215         if ( ch == 'C' ) {
216             x = Nextint();
217             for (Edge *p = fa[x]; p ; p = p->next ){
218                 int u = p->to, &T = tree[p->k];
219                 int kk = SBTAsk(T);
220                     ss[u].erase( ss[u].find(SBTAsk( T )) );
221                     if ( !mark[x] ) 
222                         SBTInsert( T , p->w );
223                     else
224                         SBTDel( T , p->w );
225                 ss[u].insert( SBTAsk( T ) );
226                 int k = get(ss[u]);
227                 if ( last[u]>0 ) ans.erase( ans.find(last[u]) );
228                 if ( k > 0 ) ans.insert( k );
229                 last[u] = k;
230             }
231             if ( mark[x] ^= 1 ) num ++;
232             else num --; 
233         }
234         else {
235             if ( num == 0 ) printf("They have disappeared.\n");
236             else 
237                 printf("%d\n" , *(--ans.end()) );
238         }
239     }
240     return 0;
241 }

 

QTREE5:把某个点的颜色从黑变成白,或者从白变成黑。。求距离某个点与其最近的白色的距离。。

显然,这个题比QTREE4相比更加合适使用点分治的方法,不过由于QTREE4写过点分治,这题就决定写树链剖分了。

点分治:1.求树中心,2.从树中心遍历整棵树,3.分成若干子树重复1。。又分治的思想可以容易证明每个节点最多只会被logn个中心遍历到,每个节点遍历到其的中心,以及距离(nlogn)。。考虑查询操作,对于每个点,其他点与其连线必然会经过这logn个中心中某一个,枚举这些中心取出树中心于对应子树中白色节点距离即可以解决。。应可以为每个树中心建立一个堆,修改操作时同样修改logn个中心上的堆即可。。(PS:QTREE4做法思想也是类似的)

树链剖分:=。=~文字好难表述。。。同理参考程序或漆子超论文吧。。

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #define N 100010
  6 #define Rep(i,n) for(int i=0;i<n;i++)
  7 using namespace std;
  8 int        ecnt;
  9 struct    Edge{
 10     int to;
 11     Edge *next;
 12 }*mat[N],edges[N*2];
 13 void    link(int x,int to){
 14     edges[ecnt].to = to;
 15     edges[ecnt].next = mat[x];
 16     mat[x] = &edges[ecnt++];
 17 }
 18 void    check(int &x,int y){
 19     if ( x == -1 || y < x ) x = y;
 20 }
 21 
 22 int        n,m;
 23 int        size[N],son[N],fa[N],dev[N],dn[N],id[N];
 24 int        tp[N],in_tree[N],cnt;
 25 void    dfs1(int x,int father){
 26     size[x] = 1;
 27     son[x] = -1;
 28     for ( Edge *p = mat[x]; p; p = p->next ){
 29         int to = p->to;
 30         if ( to == father ) continue;
 31         dfs1(to,x);
 32         fa[to] = x;
 33         dev[to] = dev[x]+1;
 34         size[x] += size[to];
 35         if ( son[x] == -1 || size[son[x]]<size[to] ) son[x] = to;
 36     }
 37 }
 38 int        dfs2(int x,int father,int top){
 39     id[in_tree[x] = ++cnt] = x;
 40     tp[x] = top;
 41     if ( son[x] == -1 ) return dn[x]=x;
 42     dn[x] = dfs2(son[x],x,top);
 43     for ( Edge *p = mat[x]; p; p = p->next ){
 44         int to = p->to;
 45         if ( to == father || to == son[x] ) continue;
 46         dfs2(to,x,to);
 47     }
 48     return dn[x];
 49 }
 50 
 51 
 52 int        in_stack[N],key[N],nn[N];
 53 vector<int>    stack[N];
 54 
 55 void    stack_swap( int k , int x,int y){
 56     swap(stack[k][x],stack[k][y]);
 57     in_stack[ stack[k][x] ] = x;
 58     in_stack[ stack[k][y] ] = y;
 59 }
 60 //x<y
 61 bool    cmp(int x,int y){
 62     if ( x == y ) return false;
 63     if ( x == -1 ) return false;
 64     if ( y == -1 ) return true;
 65     return x<y;
 66 }
 67 
 68 void    stack_up( int k , int x ){
 69     int    n = nn[k];
 70     while ( x > 1 ){
 71         if ( !cmp( key[stack[k][x]] , key[stack[k][x/2]]) )  break;
 72         stack_swap(k , x , x/2 );
 73         x /= 2; 
 74     }
 75 }
 76 
 77 void    stack_down( int k , int x ){
 78     int    n = nn[k];
 79     while ( 2*x <= n ){
 80         int t = 2*x;
 81         if ( t<n && cmp( key[stack[k][t+1]] , key[stack[k][t]] ) ) t++;
 82         if ( !cmp( key[stack[k][t]] , key[stack[k][x]] ) ) break;
 83         stack_swap(k , x , t );
 84         x = t;
 85     }
 86 }
 87 
 88 bool    mark[N];
 89 struct    Segtree{
 90     int     left[N*4],right[N*4],L[N*4],R[N*4];
 91     void    build(int l,int r,int step){
 92         left[step] = l , right[step] = r;
 93         L[step] = R[step] = -1;
 94         if ( l == r ) return;
 95         int mid = ( l + r )/2;
 96         build( l , mid , step*2 );
 97         build(mid+1, r , step*2+1);
 98     }
 99     void    updata(int w,int step){
100         if ( left[step] == right[step] ) {
101             L[step] = R[step] = mark[id[w]]?0:(nn[id[w]]?key[stack[id[w]][1]]:-1);
102             return;
103         }
104         int    mid = ( left[step] + right[step] )/2;
105         updata( w , step*2+(w>mid) );
106         L[step] = L[step*2];
107         if ( L[step*2+1] != -1 ) check( L[step] , L[step*2+1]+mid-left[step]+1 );
108         R[step] = R[step*2+1];
109         if ( R[step*2]   != -1 ) check( R[step] , R[step*2]+right[step]-mid );
110     }
111     int        ask(int w , int l ,int r,int step ){
112         int    mid = ( left[step] + right[step] )/2;
113         if ( left[step] == l && right[step] == r ) {
114             if ( w <= l ) return L[step]==-1?-1:(L[step]+l-w);
115             if ( w >= r ) return R[step]==-1?-1:(R[step]+w-r);
116         }
117         if ( r <= mid ) return ask( w, l, r , step*2 );
118         else if ( mid < l ) return ask( w , l , r , step*2+1 );
119         else{
120             int ret = ask(w,l,mid,step*2), k = ask(w,mid+1,r,step*2+1);
121             if ( k != -1 ) check( ret , ask(w,mid+1,r,step*2+1) );
122             return ret;
123         }
124     }
125 }tree;
126 
127 int        main(){
128     int    x,y;
129     scanf("%d", &n );
130     Rep(i,n-1){
131         scanf("%d%d", &x, &y );
132         link( x , y );
133         link( y , x );
134     }
135     dfs1(1,-1);
136     dfs2(1,-1,1);
137     memset( nn , 0 , sizeof(nn) );
138     memset( key ,-1, sizeof(key));
139     memset(mark, 0 , sizeof(mark));
140     tree.build(1,n,1);
141     for (int i = 1; i<=n; i++) stack[i].push_back(0);
142     for (int i = 2; i<=n; i++) 
143         if ( tp[i] == i ) {
144             stack[fa[i]].push_back(i);
145             in_stack[i] = ++nn[fa[i]];
146         }
147     scanf("%d\n" , &m );
148     int    kind , v;
149     while ( m -- ) {
150         scanf("%d%d", &kind , &v );
151         if ( kind == 0 ) {
152             mark[v] ^= 1;
153             for ( ; v ; v = fa[v] ) {
154                 tree.updata( in_tree[v] , 1 );
155                 v = tp[v];
156                 int now = tree.ask( in_tree[v] , in_tree[v] , in_tree[dn[v]] , 1 );
157                 if ( now != -1 ) now++;
158                 int last = key[v], g =mark[v]?0:(nn[v]?key[stack[v][1]]:-1) ;
159                 key[v] = now;
160                 if ( fa[v] ) {
161 //                    if ( cmp(now,key[v]) ) 
162                     stack_up( fa[v] , in_stack[v] );
163 //                    if ( cmp(key[v],now) ) 
164                     stack_down( fa[v] , in_stack[v] );
165                 }
166             }
167         }
168         else {
169             int    ans = -1;
170             for (int length = 0; v ; v = fa[tp[v]] ){
171                 int k = tree.ask(in_tree[v],in_tree[tp[v]],in_tree[dn[v]],1);
172                 if ( k != -1 )
173                     check( ans , k+length );
174                 length += in_tree[v]-in_tree[tp[v]]+1;
175                 if ( ans != -1 && length > ans ) break;
176             }
177             printf("%d\n" , ans );
178         }
179     }
180     return 0;
181 }

 

posted @ 2013-02-26 20:43  lzqxh  阅读(1132)  评论(0编辑  收藏  举报