题解【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;
}    

猜你喜欢

转载自www.cnblogs.com/h-lka/p/10993038.html