【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:最基本的树链剖分=。=
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)
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,也可以用跳表搞
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,但是经过对拍验证过其正确性
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做法思想也是类似的)
树链剖分:=。=~文字好难表述。。。同理参考程序或漆子超论文吧。。
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 }