BZOJ 4551 [Tjoi2016&Heoi2016]树

题解:动态树,维护Splay最深的被标记过的点

每个询问先Access(x);

当然用树链剖分也可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100009;
const int oo=1000000000;
 
int n,T;
 
int fa[maxn],ch[maxn][2],dest[maxn],v[maxn];
inline int son(int x){
    if(ch[fa[x]][1]==x)return 1;
    else return 0;
}
inline void pushup(int x){
    dest[x]=dest[ch[x][1]];
    if(!dest[x]){
        if(v[x])dest[x]=x;
    }
    if(!dest[x])dest[x]=dest[ch[x][0]];
}
inline bool isroot(int x){
    return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}
 
inline void Rotate(int x){
    int y=fa[x];
    int z=fa[y];
    int b=son(x),c=son(y);
    int a=ch[x][b^1];
    if(!isroot(y))ch[z][c]=x;
    fa[x]=z;
    if(a)fa[a]=y;
    ch[y][b]=a;
    fa[y]=x;ch[x][b^1]=y;
    pushup(y);pushup(x);
}
void Splay(int x){
    while(!isroot(x)){
        int y=fa[x];
        if(isroot(y)){
            Rotate(x);
        }else{
            if(son(x)==son(y)){
                Rotate(y);Rotate(x);
            }else{
                Rotate(x);Rotate(x);
            }
        }
    }
}
 
void Access(int x){
    for(int t=0;x;t=x,x=fa[x]){
        Splay(x);ch[x][1]=t;pushup(x);
    }
}
 
 
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
     nex[++cntedge]=head[x];
     to[cntedge]=y;
     head[x]=cntedge;
}
 
queue<int>q;
int father[maxn];
void Bfs(){
    q.push(1);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nex[i]){
            if(to[i]==father[x])continue;
            father[to[i]]=x;
            fa[to[i]]=x;
            q.push(to[i]);
        }
    }
}
 
int main(){
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n-1;++i){
        int x,y;
        scanf("%d%d",&x,&y);
        Addedge(x,y);
        Addedge(y,x);
    }
     
    v[1]=1;dest[1]=1;
    Bfs();
    while(T--){
        char opty[10];
        scanf("%s",opty);
        int x;
        scanf("%d",&x);
        if(opty[0]=='C'){
            Splay(x);v[x]=1;pushup(x);
        }else{
            Access(x);Splay(x);printf("%d\n",dest[x]);
        }
    }
    return 0;
}

  

posted @   ws_zzy  阅读(136)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示