SPOJ 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).
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的更多相关文章
- 2019.02.17 spoj Query on a tree V(链分治)
传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...
- QTREE5 - Query on a tree V——LCT
QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...
- 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 ...
- SPOJ QTREE Query on a tree V ——动态点分治
[题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...
- SPOJ - QTREE5 Query on a tree V 边分治
题目传送门 题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少. 题解: 这里用的还是边分治的方法. 把所有东西都抠 ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Spoj Query on a tree III
题目描述 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑点,若无,输出 ...
- 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 ...
- 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. ...
随机推荐
- 乐动力APP案例
第一部分 调研, 评测 下载软件并使用起来,描述最简单直观的个人第一次上手体验. 这款软件的主界面功能还是比较完善,里面有多个关于运动相关的数据,还有一些推荐健身教程,记录功能也十分不错,其中最难理解 ...
- zookeeper提示Unable to read additional data from server sessionid 0x
配置zookeeper集群,一开始配置了两台机器server.1和server.2. 配置参数,在zoo.cfg中指定了整个zookeeper集群的server编号.地址和端口: server.1=1 ...
- JDBC操作数据库的三种方式比较
JDBC(java Database Connectivity)java数据库连接,是一种用于执行上sql语句的javaAPI,可以为多种关系型数据库提供统一访问接口.我们项目中经常用到的MySQL. ...
- 一句话了解JAVA与大数据之间的关系
大数据无疑是目前IT领域的最受关注的热词之一.几乎凡事都要挂上点大数据,否则就显得你OUT了.如果再找一个可以跟大数据并驾齐驱的IT热词,JAVA无疑是跟大数据并驾齐驱的一个词语.很多人在提到大数据的 ...
- 在网络编程中的io流小问题
在客户端和服务端调用io流进行传输数据的过程中,当将数据write到outputstream中,需要及时刷新,否则会发生io阻塞. 在输入数据的时候,最好选用BufferedReader,因为read ...
- vuex - 项目结构目录及一些简单配置
首先先正经的来一段官网的"忠告": vuex需要遵守的规则: 一.应用层级的状态应该集中到单个 store 对象中. 二.提交 mutation 是更改状态的唯一方法,并且这个过程 ...
- python生成单词壁纸
1.首先上结果: 其实就是一段简单的代码.加上英语单词表加上几张背景图生成许多类似的图片再设置成桌面背景,十分钟一换.有心的人闲的时候随手就能换换桌面背背单词.最不济也能混个脸熟. 3.上代码 #-* ...
- SpringCloud的应用发布(四)顺序启动各个应用
一.部署应用 二.启动应用(注意顺序) 三.观察效果 1.查看进程和日志 ps -ef | grep java tail -f AppYml.txt 2.验证功能
- Docker学习笔记 - Docker的镜像
一个容器实际上是运行在宿主机上的一个进程. 只不过在启动这个进程之前进行了一些特殊处理,让这个容器进入了一个全新的虚拟环境,与宿主机的环境分开, 所以这个进程及其子进程认为自己运行在一个独立的世界里面 ...
- SpringBoot(五):@ConfigurationProperties配置参数绑定
在springmvc或其他ssh框架中如果我们要实现一个配置参数的加载,需要使用代码实现读取properties文件等操作,或者需要使用其他属性@value(name="username&q ...