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.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- java--creater in windows
电脑右键--高级--属性--更改环境变量 1.JAVA_HOME C:\Program Files\Java\jdk1.7.0_04 2. Path %JAV ...
- nuxt.js express模板项目IIS部署
继续上一篇的nuxt/express项目部署,还是windows上要把nuxt的服务端渲染项目跑起来,这次的目的是用已经有的域名windows服务器上一个虚拟目录反向代理部署在其他端口nuxt项目. ...
- Dialogue between Jack and Rose【jack 和 Rose的对话】
Dialogue between Jack and Rose Rose : It's getting quiet. 越来越安静了 Jack : It's gonna take a couple of ...
- C++多态实例
#include <iostream> #include <string> using namespace std; //class 实现 class Employee { s ...
- Linux 内核源码外编译 linux模块--编译驱动模块的基本方法
1.先编写一个简单的hello模块,hello.c 源码如下: #ifndef __KERNEL__ # define __KERNEL__ #endif #ifndef MODULE # defin ...
- 按位与&、或|、异或^等运算方法
(转载) 按位与运算符(&) 参加运算的两个数据,按二进制位进行“与”运算. 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; ...
- eeeeeeeeeee
http://58.241.123.38/hot.cdn.baidupcs.com/file/91623e76f776475da9c3223cdac861f0?xcode=68983c005f6e3c ...
- SQLite学习和使用
创建数据库并创建表格 1.创建MyDatabaseHelper继承于SQLiteOpenHelper(抽象类,必须实现onCreate()和onUpgrade()方法)2.把数据库建表指令弄成一个字符 ...
- DEDE调用指定文章ID来调用特定文档
http://www.jb51.net/cms/137423.html 代码如下: {dede:arclist row=1 idlist='6'} <li><a href=" ...
- 使用 CommandScene 类在 XNA 中创建命令场景(十二)
平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...