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提为根,那么结点上记录的“离右端点最近的白点距离”就是答案了。

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

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
const int INF=1e7;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int fir(multiset<int> &s){return s.size()? *s.begin():INF;}
struct edge{
int v,nxt;
}e[mxn<<];
int hd[mxn],mct=;
void add_edge(int u,int v){
e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
}
//
struct node{int ch[],fa;}t[mxn];
multiset<int>pt[mxn];
int len[mxn],L[mxn],R[mxn],sum[mxn],mians[mxn];
int w[mxn],col[mxn];
void init(int n){
for(int i=;i<=n;i++)w[i]=INF,col[i]=;
for(int i=;i<=n;i++){L[i]=R[i]=mians[i]=INF;}
return;
}
inline bool isroot(int x){return (t[t[x].fa].ch[]!=x && t[t[x].fa].ch[]!=x);}
void pushup(int x){
if(!x)return;
int lc=t[x].ch[],rc=t[x].ch[];
sum[x]=len[x]+sum[lc]+sum[rc];
int m0=min(w[x],fir(pt[x]));
// printf("m0:%d\n",m0);
int ml=min(R[lc]+len[x],m0);
int mr=min(L[rc],m0);
L[x]=min(L[lc],sum[lc]+len[x]+mr);
R[x]=min(R[rc],sum[rc]+ml);
return;
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa,lc,rc;
if(t[y].ch[]==x)lc=;else lc=;rc=lc^;
if(!isroot(y)){t[z].ch[t[z].ch[]==y]=x;}
t[x].fa=z;t[y].fa=x;
t[t[x].ch[rc]].fa=y;t[y].ch[lc]=t[x].ch[rc];
t[x].ch[rc]=y;
pushup(y);
return;
}
void Splay(int x){
while(!isroot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isroot(y)){
if((t[y].ch[]==x)^(t[z].ch[]==y))rotate(x);
else rotate(y);
}
rotate(x);
}
pushup(x);
return;
}
void access(int x){
for(int y=;x;x=t[x].fa){
Splay(x);
if(t[x].ch[]){pt[x].insert(L[t[x].ch[]]);}
if(y) pt[x].erase(pt[x].find(L[y]));
t[x].ch[]=y;
pushup(x);
y=x;
}
return;
}
void change(int x){
access(x);Splay(x);
// printf("col:%d\n",col[x]);
col[x]^=;
// printf("col:%d\n",col[x]);
if(!col[x])w[x]=;else w[x]=INF;
// printf("!!!change:%d to %d\n",x,w[x]);
pushup(x);
return;
}
int query(int x){
access(x);
Splay(x);
pushup(x);
return R[x];
}
//LCT
void DFS(int u,int fa){
for(int i=hd[u];i;i=e[i].nxt){
if(e[i].v==fa)continue;int v=e[i].v;
t[v].fa=u;
len[v]=;
DFS(v,u);
// pt[u].insert(mians[v]);
pt[u].insert(L[v]);
}
pushup(u);
return;
}
int n,Q;
int main(){
int i,j,u,v;
n=read();
for(i=;i<n;i++){
u=read();v=read();
add_edge(u,v);
add_edge(v,u);
}
init(n);
DFS(,);
Q=read();
while(Q--){
u=read();v=read();
if(u){
int ans=query(v);
if(ans>=INF)printf("-1\n");
else printf("%d\n",ans);
}
else{change(v);}
}
return ;
}

SPOJ QTREE Query on a tree V的更多相关文章

  1. SPOJ QTREE Query on a tree V ——动态点分治

    [题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...

  2. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

  3. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  4. SPOJ QTREE Query on a tree --树链剖分

    题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...

  5. SPOJ QTREE Query on a tree VI

    You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are number ...

  6. SPOJ QTREE - Query on a tree 【树链剖分模板】

    题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...

  7. SPOJ QTREE Query on a tree

    题意:给一颗n个点的树,有两种操作CHANGE i ti : 把第i条边的权变为tiQUERY a b : 问点a 到 点b 之间的边的最大权 思路:树剖处理边权.由于是边,所以只需要把边权处理到子节 ...

  8. SPOJ QTREE Query on a tree ——树链剖分 线段树

    [题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...

  9. SPOJ - QTREE Query on a tree题解

    题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...

随机推荐

  1. git出现误修改如何撤销

    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file. 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步, ...

  2. C++性能优化笔记

    最近着手去优化项目中一个模块的性能.该模块是用C++实现,对大量文本数据进行处理. 一开始时,没什么思路,因为不知道性能瓶颈在哪里.于是借助perf工具来对程序进行分析,找出程序的性能都消耗在哪里了. ...

  3. 初学puppet

    初学puppet puppet是什么? puppet是一个开源的软件自动化配置和部署工具,很多大型IT公司均在使用puppet对集群中的软件进行管理和部署. Puppet简介 Puppet的目录是让管 ...

  4. 选择 NoSQL 数据库需要考虑的 10 个问题

    那么我为什么要写这篇文章呢? 是因为我认为NoSQL解决方案不如RDBMS解决方案吗?当然不! 是因为我专注于SQL的做事方式,而不想陷入一种相对较新的技术的不确定性吗?不,也不是!事实上,我非常兴奋 ...

  5. 动态规划:HDU1176-免费馅饼

    免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  6. CodeForces 781E Andryusha and Nervous Barriers 线段树 扫描线

    题意: 有一个\(h \times w\)的矩形,其中有\(n\)个水平的障碍.从上往下扔一个小球,遇到障碍后会分裂成两个,分别从障碍的两边继续往下落. 如果从太高的地方落下来,障碍会消失. 问从每一 ...

  7. Go语言之并发编程(三)

    Telnet回音服务器 Telnet协议是TCP/IP协议族中的一种.它允许用户(Telnet客户端)通过一个协商过程与一个远程设备进行通信.本例将使用一部分Telnet协议与服务器进行通信. 服务器 ...

  8. sql server 不可见字符处理 总结

    前言 问题描述:在表列里有肉眼不可见字符,导致一些更新或插入失败. 几年前第一次碰见这种问题是在读取考勤机人员信息时碰见的,折腾了一点时间,现在又碰到了还有点新发现就顺便一起记录下. 如下图所示 go ...

  9. 了解JavaScript核心精髓(二)

    1.字符串操作 //声明字符串 var str = "abcd"; var str = new String("abcd") //截取字符串 console.l ...

  10. live 555 freebsd 或centos 7.4 实现代理视频直播服务

    live 555   freebsd 或centos 7.4 实现代理视频直播服务 the live555 media server    在线直播服务器 关于此服务器 此服务是一个无安全的rtsp服 ...