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.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- Django 模型与 Mysql 数据类型对应
Django 1.11.9 文件路径:site-packages\django\db\backends\mysql\base.py–class DatabaseWrapper _data_types ...
- PAT 乙级 1024
题目 题目地址:PAT 乙级 1024 题解 模拟题,重点需要考虑到各种不同情况:简单来说一下: 因为输入格式固定,所以把不同的部分分别存储和处理可以在很大程度上简化运算:其中需要考虑最多的就是小数部 ...
- mysql 查询条件 默认不区分大小写
mysql查询默认是不区分大小写的 如: 1 2 select * from some_table where str=‘abc'; select * from some_table where st ...
- IE支持直接查看Json数据注册表代码
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/json] ...
- (转)规划从 OpenGL ES 2.0 到 Direct3D 的移植
如果你移植 iOS 或 Android 平台中的游戏,那么你可能需要在 OpenGL ES 2.0 方面进行大量投资.如果你准备将你的图形管道代码库移动到 Direct3D 11 和 Windows ...
- POJ 2299 Ultra-QuickSort 简单题解
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 68874 Accepted: 25813 ...
- Python数据类型的用法
字符串的用法 res = 'hellow,world' print(res) #res.显示的都是它的方法,下划线的除外 1 判断字符串的结尾字符,返回的值的布尔形式 endswith 判断字符串的开 ...
- Codeforces Round #496 (Div. 3) ABCDE1
//B. Delete from the Left #include <iostream> #include <cstdio> #include <cstring> ...
- DiyCode开源项目 AboutActivity分析
1.首先看一下效果 这是手机上显示的效果: 1.1首先是一个标题栏,左侧一个左箭头,然后一个图标. 1.2然后下方是一个可以滑动的页面. 1.3分成了7个部分. 1.4DiyCode的图标. 1.5然 ...
- 57、android 应用内全局通知的实现方法
1.后台运行一个服务 间隔5s从服务器获取一次数据,根据业务需要,当需要提醒给用户时,从右侧自动划出 类似效果如下:在任何界面都会有通知弹窗 2.实现过程 ①android的根布局叫dector( ...