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).
- 1 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的更多相关文章
- SPOJ QTREE Query on a tree V ——动态点分治
[题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...
- 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 ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- SPOJ QTREE Query on a tree --树链剖分
题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...
- 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 ...
- SPOJ QTREE - Query on a tree 【树链剖分模板】
题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...
- SPOJ QTREE Query on a tree
题意:给一颗n个点的树,有两种操作CHANGE i ti : 把第i条边的权变为tiQUERY a b : 问点a 到 点b 之间的边的最大权 思路:树剖处理边权.由于是边,所以只需要把边权处理到子节 ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- SPOJ - QTREE Query on a tree题解
题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- Android驱动开发读书笔记七
第七章 (一)创建设备文件 1.使用cdev_init函数初始化cdec 描述设备文件需要一个cdev结构体,代码如下: struct cdev{ struct kobject kobj; struc ...
- 学习笔记(七): Logistic Regression
目录 Calculating a Probability Model Training 1.Loss function for Logistic Regression 2.Regularization ...
- 该网页无法正常运作 目前无法处理此请求HTTP ERROR 500?
由于php.ini配置文件中错误显示关闭导致. 将下值由Off 变更为 On display_errors = On display_startup_errors = On
- 四 python并发编程之协程
一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...
- 【Ecshop】将内置的 FCkeditor 更换为 UEditor
1.下载UE,解压到includes/,更名目录名为ueditor 注意更改配置后端文件上传路径,参考文档 2.修改admin/includes/lib_main.php,添加 /** * 生成编辑器 ...
- jQuery的三种写法
jQuery的三种写法 jQuery一共有三种写法,写法如下: <script type="text/javascript" src="js/jquery-1.9. ...
- 科学计算库Numpy——排序
矩阵按维度排序 使用np.sort()进行排序. 排序索引值 使用np.argsort()排序,返回排序后的索引值. 备注:array1[1,2]=1.2,array1[1,0]=5.6,array1 ...
- python面试题之介绍一下Python中webbrowser的用法
所属网站分类: 面试经典 > python 作者:外星人入侵 链接: http://www.pythonheidong.com/blog/article/13/ 来源:python黑洞网 www ...
- python正则表达式入门篇
文章来源于:https://www.cnblogs.com/chuxiuhong/p/5885073.html Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. ...
- MySQL基础9-主键约束、外键约束、等值连接查询、一对一和多对多关系
1.主键约束和外键约束 外键约束 * 外键必须是另一表的主键的值(外键要引用主键!) * 外键可以重复 * 外键可以为空 * 一张表中可以有多个外键! 概念模型在数据库中成为表 数据库表中的多对一关系 ...