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).

1 v : ask for the minimum dist(u, v), node u must be white(u can be equal to v). 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

解题报告:

写了这个题之后算是对点分治有了个新认识,感觉以前写的都是假的啊.

突然发现任意两个点之间的路径仿佛都只会交在一个重心上,这样我们就很好弄了,对每一个重心维护一个小根堆,如果0操作弄出一个白点,我们就把这个白点加入到包含它的重心所在的堆里面,然后询问就直接查询包含该点的重心,用\(disi,v+q[i].top()\)去更新答案,i为某重心,q为该重心的堆,复杂度\(O(nlog2n)\)

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=100005,inf=2e8;
int gi(){
int str=0;char ch=getchar();
while(ch>'9' || ch<'0')ch=getchar();
while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
return str;
}
int n,num=0,head[N],to[N<<1],nxt[N<<1],root=0,f[N]={inf},son[N],sum;
bool vis[N];
struct node{
int x,id;
bool operator <(const node &pp)const{
return x>pp.x;
}
};
priority_queue<node>q[N];
void link(int x,int y){
nxt[++num]=head[x];to[num]=y;head[x]=num;
}
int Head[N],NUM=0,To[N*30],Dis[N*30],Next[N*30];
void add(int x,int y,int z){
Next[++NUM]=Head[x];To[NUM]=y;Dis[NUM]=z;Head[x]=NUM;
}
bool col[N];
void getdis(int x,int last,int dist){
add(x,root,dist);
int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last || vis[u])continue;
getdis(u,x,dist+1);
}
}
void getroot(int x,int last){
int u;son[x]=1;f[x]=0;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(vis[u] || u==last)continue;
getroot(u,x);
son[x]+=son[u];
f[x]=Max(f[x],son[u]);
}
f[x]=Max(f[x],sum-son[x]);
if(f[x]<f[root])root=x;
}
void dfs(int x){
int u;vis[x]=true;
getdis(x,x,0);
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(vis[u])continue;
root=0;sum=son[u];getroot(u,x);
dfs(root);
}
}
void updata(int x){
col[x]^=1;
if(col[x])
for(int i=Head[x];i;i=Next[i])
q[To[i]].push((node){Dis[i],x});
}
int query(int x){
if(col[x])return 0;
int ret=inf;
for(int i=Head[x];i;i=Next[i]){
int u=To[i];
while(!q[u].empty() && !col[q[u].top().id])q[u].pop();
if(!q[u].empty())ret=Min(ret,q[u].top().x+Dis[i]);
}
return ret==inf?-1:ret;
}
void work()
{
int x,y;
n=gi();
for(int i=1;i<n;i++){
x=gi();y=gi();
link(x,y);link(y,x);
}
sum=n;root=0;getroot(1,1);
dfs(root);
int Q=gi(),flag;
while(Q--){
flag=gi();x=gi();
if(!flag)updata(x);
else printf("%d\n",query(x));
}
} int main()
{
work();
return 0;
}

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

  1. 2019.02.17 spoj Query on a tree V(链分治)

    传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...

  2. QTREE5 - Query on a tree V——LCT

    QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...

  3. SPOJ QTREE Query on a tree V

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

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

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

  5. SPOJ - QTREE5 Query on a tree V 边分治

    题目传送门 题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少. 题解: 这里用的还是边分治的方法. 把所有东西都抠 ...

  6. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  7. Spoj Query on a tree III

    题目描述 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑点,若无,输出 ...

  8. SPOJ Query on a tree III (树剖(dfs序)+主席树 || Splay等平衡树)(询问点)

    You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose ...

  9. SPOJ QTREE4 SPOJ Query on a tree IV

    You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3. ...

随机推荐

  1. python之路--day13---函数--三元表达式,递归,匿名函数,内置函数-----练习

    1.文件内容如下,标题为:姓名,性别,年纪,薪资 egon male 18 3000 alex male 38 30000 wupeiqi female 28 20000 yuanhao female ...

  2. STM32F4系列单片机上使用CUBE配置MBEDTLS实现pem格式公钥导入

    |版权声明:本文为博主原创文章,未经博主允许不得转载. 最近尝试在STM32F4下用MBEDTLS实现了公钥导入(我使用的是ECC加密),整个过程使用起来比较简单. 首先,STM32F4系列CUBE里 ...

  3. .Net Core MongoDB 简单操作。

    一:MongoDB 简单操作类.这里引用了MongoDB.Driver. using MongoDB.Bson; using MongoDB.Driver; using System; using S ...

  4. C#日志文件

    写日志文件是一个很常用的功能,以前都是别人写好的,直接调用的,近期写了一个小工具,因为比较小,所以懒得引用dll文件了,直接上网找了一个,很方便,现在记录下 public class LogClass ...

  5. 用Jmeter实现mysql数据库的增删查改

    主要是参考虫师的“使用JMeter创建数据库(Mysql)测试”. 1.打开Jmeter,点击测试计划 链接:https://pan.baidu.com/s/1ZtaZ6IC_0DRjSlXkjslY ...

  6. SendMessage 遇到的神坑

    场景 两个进程A和B,需要从A中设置B中的文本框的内容 过程 x.x.x.x. 成功获取了B中的内容,惊喜,离成功更近异步 xxxx ***** ....... x.x.x.x. 大约查找了几百个网页 ...

  7. python基础——面向过程的编程思想及举例

    面向过程的编程思想 1.面向过程的编程思想及举例 写程序时: 要先想功能,分步实现 2. os模块中walk输出目录中文件路径 os.walk() 方法用于通过在目录树中游走输出在目录中的文件名,向上 ...

  8. CSS属性操作/下

    CSS属性操作/下 1.伪类 anchor伪类 跟<a>/</a>有关:专用于控制链接的显示效果 a:link(没有接触过的链接),用于定义了链接的常规状态. a:hover( ...

  9. hdu2674 N!Again---思维

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2674 题目大意: 求n!%2009的值 思路: 由于模2009,所以大于等于2009的直接为0,前2 ...

  10. hdu1051 Wooden Sticks---贪心

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1051 题目大意:给你n根木棍的长度和重量.根据要求求出制作该木棍的最短时间.建立第一个木棍需要1分钟 ...