SPOJ QTREE Query on a tree V

You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. We define dist(a, b) as the number of edges on the path from node a to node b.

Each node has a color, white or black. All the nodes are black initially.

We will ask you to perfrom some instructions of the following form:

  • 0 i : change the color of i-th node(from black to white, or from white to black).
  • v : ask for the minimum dist(u, v), node u must be white(u can be equal tov). Obviously, as long as node v is white, the result will always be 0.

Input

  • In the first line there is an integer N (N <= 100000)
  • In the next N-1 lines, the i-th line describes the i-th edge: a line with two integers a b denotes an edge between a and b.
  • In the next line, there is an integer Q denotes the number of instructions (Q <= 100000)
  • In the next Q lines, each line contains an instruction "0 i" or "1 v"

Output

For each "1 v" operation, print one integer representing its result. If there is no white node in the tree, you should write "-1".

Example

Input:
10
1 2
1 3
2 4
1 5
1 6
4 7
7 8
5 9
1 10
10
0 6
0 6
0 6
1 3
0 1
0 1
1 3
1 10
1 4
1 6

Output:
2
2
2
3
0

 

改变某点颜色,或者询问离某点最近的白点离询问点的距离

 

LCT

在LCT上,把未激活的树枝全丢到set里。

花式更新状态,记录链左端点的最近白点距离,右端点的最近白点距离。注意更新左边来(深度更浅处)的答案时,要加上下放到当前点的边权。

统计答案时,access(x),使得x在当前链的最右端,Splay(x)将x提为根,那么结点上记录的“离右端点最近的白点距离”就是答案了。

 

说着简单,调了三四个小时,也是绝望(然而只是绝望的开始)

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<set>
  8 using namespace std;
  9 const int INF=1e7;
 10 const int mxn=100010;
 11 int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 int fir(multiset<int> &s){return s.size()? *s.begin():INF;}
 18 struct edge{
 19     int v,nxt;
 20 }e[mxn<<1];
 21 int hd[mxn],mct=0;
 22 void add_edge(int u,int v){
 23     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 24 }
 25 //
 26 struct node{int ch[2],fa;}t[mxn];
 27 multiset<int>pt[mxn];
 28 int len[mxn],L[mxn],R[mxn],sum[mxn],mians[mxn];
 29 int w[mxn],col[mxn];
 30 void init(int n){
 31     for(int i=0;i<=n;i++)w[i]=INF,col[i]=1;
 32     for(int i=0;i<=n;i++){L[i]=R[i]=mians[i]=INF;}
 33     return;
 34 }
 35 inline bool isroot(int x){return (t[t[x].fa].ch[0]!=x && t[t[x].fa].ch[1]!=x);}
 36 void pushup(int x){
 37     if(!x)return;
 38     int lc=t[x].ch[0],rc=t[x].ch[1];
 39     sum[x]=len[x]+sum[lc]+sum[rc];
 40     int m0=min(w[x],fir(pt[x]));
 41 //    printf("m0:%d\n",m0);
 42     int ml=min(R[lc]+len[x],m0);
 43     int mr=min(L[rc],m0);
 44     L[x]=min(L[lc],sum[lc]+len[x]+mr);
 45     R[x]=min(R[rc],sum[rc]+ml);
 46     return;
 47 }
 48 void rotate(int x){
 49     int y=t[x].fa,z=t[y].fa,lc,rc;
 50     if(t[y].ch[0]==x)lc=0;else lc=1;rc=lc^1;
 51     if(!isroot(y)){t[z].ch[t[z].ch[1]==y]=x;}
 52     t[x].fa=z;t[y].fa=x;
 53     t[t[x].ch[rc]].fa=y;t[y].ch[lc]=t[x].ch[rc];
 54     t[x].ch[rc]=y;
 55     pushup(y);
 56     return;
 57 }
 58 void Splay(int x){
 59     while(!isroot(x)){
 60         int y=t[x].fa,z=t[y].fa;
 61         if(!isroot(y)){
 62             if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x);
 63             else rotate(y);
 64         }
 65         rotate(x);
 66     }
 67     pushup(x);
 68     return;
 69 }
 70 void access(int x){    
 71     for(int y=0;x;x=t[x].fa){
 72         Splay(x);
 73         if(t[x].ch[1]){pt[x].insert(L[t[x].ch[1]]);}
 74         if(y) pt[x].erase(pt[x].find(L[y]));
 75         t[x].ch[1]=y;
 76         pushup(x);
 77         y=x;
 78     }
 79     return;
 80 }
 81 void change(int x){
 82     access(x);Splay(x);
 83 //    printf("col:%d\n",col[x]);
 84     col[x]^=1;
 85 //    printf("col:%d\n",col[x]);
 86     if(!col[x])w[x]=0;else w[x]=INF;
 87 //    printf("!!!change:%d  to %d\n",x,w[x]);
 88     pushup(x);
 89     return;
 90 }
 91 int query(int x){
 92     access(x);
 93     Splay(x);
 94     pushup(x);
 95     return R[x];
 96 }
 97 //LCT
 98 void DFS(int u,int fa){
 99     for(int i=hd[u];i;i=e[i].nxt){
100         if(e[i].v==fa)continue;int v=e[i].v;
101         t[v].fa=u;
102         len[v]=1;
103         DFS(v,u);
104 //        pt[u].insert(mians[v]);
105         pt[u].insert(L[v]);
106     }
107     pushup(u);
108     return;
109 }
110 int n,Q;
111 int main(){
112     int i,j,u,v;    
113     n=read();
114     for(i=1;i<n;i++){
115         u=read();v=read();
116         add_edge(u,v);
117         add_edge(v,u);
118     }
119     init(n);
120     DFS(1,0);
121     Q=read();
122     while(Q--){
123         u=read();v=read();
124         if(u){
125             int ans=query(v);
126             if(ans>=INF)printf("-1\n");
127             else printf("%d\n",ans);
128         }
129         else{change(v);}
130     }
131     return 0;
132 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6481764.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值