题解QTree3
Posted h-lka
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解QTree3相关的知识,希望对你有一定的参考价值。
题目描述
给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白
有两种操作:
0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)
1 v : 询问1到v的路径上的第一个黑点,若无,输出-1
输入输出格式
输入格式:
第一行 N,Q,表示N个点和Q个操作
第二行到第N行N-1条无向边
再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).
输出格式:
对每个1 v操作输出结果
输入输出样例:
9 8 1 2 1 3 2 4 2 9 5 9 7 9 8 9 6 8 1 3 0 8 1 6 1 7 0 2 1 9 0 2 1 9
输出:
-1 8 -1 2 -1
解:
题意要求我们单点修改颜色,查询距离。
这题当然不止LCT一种做法,也可以树剖。最近学了下LCT就练了一下QwQ.
我们先用一遍dfs求深度。求出深度后,LCT中维护除正常信息之外,维护点子树中黑点深度最浅的id编号以及点的col。
pushup:
inline void pushup(int x) if(tr[x].col)tr[x].id=x; else tr[x].id=0; if(dep[tr[tr[x].ch[0]].id]<dep[tr[x].id])tr[x].id=tr[tr[x].ch[0]].id; if(dep[tr[rc].id]<dep[tr[x].id])tr[x].id=tr[rc].id;
这个就不说了吧。
由于要dfs求深度,用前向星存边(树剖基本操作qwq),dfs即可。
(学树剖的话一定敲一下旅游那道题,基础操作比较全。)
记住,先dfs再Link!
每次单点修改,makeroot之后col^=1。
查询把v和1(伪根)split一下输出id即可。
代码:
#include<cstdio> #define MAXN 500000 #include<iostream> using namespace std; #define lc tr[x].ch[0] #define rc tr[x].ch[1] struct node int ch[2],fa,rev,id,col; tr[500000]; int n,m,dep[MAXN],head[MAXN]; int tot,a[MAXN],b[MAXN],opt,f; struct EDGE int next,to; e[MAXN]; inline bool root(int x) int g=tr[x].fa; return !(tr[g].ch[1]==x||tr[g].ch[0]==x); inline void pushup(int x) if(tr[x].col)tr[x].id=x; else tr[x].id=0; if(dep[tr[tr[x].ch[0]].id]<dep[tr[x].id])tr[x].id=tr[tr[x].ch[0]].id; if(dep[tr[rc].id]<dep[tr[x].id])tr[x].id=tr[rc].id; inline void pushr(int x) if(!x)return; swap(tr[x].ch[0],tr[x].ch[1]); tr[x].rev^=1; inline void pushdown(int x) if(tr[x].rev) pushr(tr[x].ch[0]); pushr(tr[x].ch[1]); tr[x].rev=0; inline void push(int x) if(!root(x))push(tr[x].fa); pushdown(x); inline void rotate(int x) int y=tr[x].fa,z=tr[y].fa,k=tr[y].ch[1]==x; if(!root(y))tr[z].ch[tr[z].ch[1]==y]=x; tr[x].fa=z;tr[y].ch[k]=tr[x].ch[k^1]; if(tr[x].ch[k^1])tr[tr[x].ch[k^1]].fa=y; tr[y].fa=x;tr[x].ch[k^1]=y; pushup(y);pushup(x); inline void splay(int x) int y,z; push(x); while(!root(x)) y=tr[x].fa,z=tr[y].fa; if(!root(y))(tr[z].ch[0]==y)^(tr[y].ch[0]==x)?rotate(x):rotate(y); rotate(x); pushup(x); inline void access(int x)for(int y=0;x;y=x,x=tr[x].fa)splay(x);tr[x].ch[1]=y;pushup(x); inline void makeroot(int x) access(x);splay(x);pushr(x); inline void split(int x,int y) makeroot(x);access(y);splay(y); inline void link(int x,int y) makeroot(x);tr[x].fa=y; inline void add(int x,int y) e[++tot].to=y; e[tot].next=head[x]; head[x]=tot; inline void dfs(int u,int fa) dep[u]=dep[fa]+1; for(register int i=head[u] ; i ; i=e[i].next) if(e[i].to!=fa) dfs(e[i].to,u); int main() // link(1,2);link(1,3); scanf("%d%d",&n,&m); for(int i=1;i<n;++i) scanf("%d%d",&a[i],&b[i]); add(a[i],b[i]);add(b[i],a[i]); dep[0]=0; dfs(1,0); //printf("Case:1#\n"); dep[0]=2147483647; // printf("Case:3#\n"); for(int i=1;i<n;++i)/*printf("Step%d %d %d\n",i,a[i],b[i]),*/link(a[i],b[i])/*,printf("Case:4#%d\n",i)*/; // printf("Case:2#\n"); for(int i=1;i<=m;++i) scanf("%d%d",&opt,&f); if(!opt)makeroot(f),tr[f].col^=1; else split(1,f); printf("%d\n",tr[f].id==0?-1:tr[f].id); return 0;
地理中考:
... int main() int grades=0,rp=0; while(727) rp++;grades++; return 0;
以上是关于题解QTree3的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ QTREE3 - Query on a tree again!