传送门


注意到每一次\(1\ x\)操作相当于一次LCT中的access操作。由LCT复杂度证明可以知道access的总次数不会超过\(O(nlogn)\),我们只需要模拟这个access的过程并在其中动态统计每一个点的答案。

我们考虑在虚实边切换的过程中即时更新答案。设当前即将把\(y \rightarrow x\)的虚边转换为实边,设此时\(x\)的实儿子为\(p\)。那么对于\(p\)及其子树,所有点到根的路径经过的颜色数量均\(+1\);对于\(y\)及其所有点的子树,它们经过的颜色的数量均\(-1\)。那么我们只需要实现子树加减,可以使用线段树。

对于\(3\)操作也就是一个子树\(\max\)操作,同样在线段树上维护;\(2\)操作可以知道\(val_{x,y} = val_{1,x} + val_{1,y} - 2val_{1,LCA(x,y)} + 1\),所以就是线段树上的单点查询。

#include<bits/stdc++.h>
using namespace std; int read(){
int a = 0; char c = getchar(); bool f = 0;
while(!isdigit(c)){f = c == '-'; c = getchar();}
while(isdigit(c)){
a = a * 10 + c - 48; c = getchar();
}
return f ? -a : a;
} const int _ = 1e5 + 7;
vector < int > ch[_];
int N , M , dep[_] , dfn[_] , sz[_] , ind[_] , ts , jump[_][20]; namespace segt{
int mx[_ << 2] , mrk[_ << 2]; #define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1) void init(int x , int l , int r){
if(l == r) mx[x] = dep[ind[l]];
else{init(lch , l , mid); init(rch , mid + 1 , r); mx[x] = max(mx[lch] , mx[rch]);}
} void mark(int x , int val){mrk[x] += val; mx[x] += val;}
void down(int x){mark(lch , mrk[x]); mark(rch , mrk[x]); mrk[x] = 0;} void modify(int x , int l , int r , int L , int R , int val){
if(l >= L && r <= R) return mark(x , val);
down(x);
if(mid >= L) modify(lch , l , mid , L , R , val);
if(mid < R) modify(rch , mid + 1 , r , L , R , val);
mx[x] = max(mx[lch] , mx[rch]);
} int qry(int x , int l , int r , int L , int R){
if(l >= L && r <= R) return mx[x];
int mx = 0; down(x);
if(mid >= L) mx = qry(lch , l , mid , L , R);
if(mid < R) mx = max(mx , qry(rch , mid + 1 , r , L , R));
return mx;
}
#undef lch
#undef rch
} namespace LCT{
int fa[_] , ch[_][2]; bool son(int x){return ch[fa[x]][1] == x;}
bool nroot(int x){return ch[fa[x]][1] == x || ch[fa[x]][0] == x;} void rot(int x){
bool f = son(x); int y = fa[x] , z = fa[y] , w = ch[x][f ^ 1];
fa[x] = z; if(nroot(y)) ch[z][son(y)] = x;
fa[y] = x; ch[x][f ^ 1] = y;
ch[y][f] = w; if(w) fa[w] = y;
} void splay(int x){while(nroot(x)){if(nroot(fa[x])) rot(son(fa[x]) == son(x) ? fa[x] : x); rot(x);}} void access(int x){
for(int y = 0 ; x ; y = x , x = fa[x]){
splay(x);
if(ch[x][1]){
int t = ch[x][1]; while(ch[t][0]) t = ch[t][0];
segt::modify(1 , 1 , N , dfn[t] , dfn[t] + sz[t] - 1 , 1);
}
if(y){
int t = y; while(ch[t][0]) t = ch[t][0];
segt::modify(1 , 1 , N , dfn[t] , dfn[t] + sz[t] - 1 , -1);
}
ch[x][1] = y; fa[y] = x;
}
}
} void dfs(int x , int p){
dep[x] = dep[p] + 1; ind[dfn[x] = ++ts] = x; sz[x] = 1;
jump[x][0] = p; LCT::fa[x] = p;
for(int i = 1 ; jump[x][i - 1] ; ++i) jump[x][i] = jump[jump[x][i - 1]][i - 1];
for(auto t : ch[x]) if(t != p){dfs(t , x); sz[x] += sz[t];}
} int LCA(int x , int y){
if(dep[x] < dep[y]) swap(x , y);
for(int i = 18 ; i >= 0 ; --i)
if(dep[x] - (1 << i) >= dep[y]) x = jump[x][i];
if(x == y) return x;
for(int i = 18 ; i >= 0 ; --i)
if(jump[x][i] != jump[y][i]){x = jump[x][i]; y = jump[y][i];}
return jump[x][0];
} int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
N = read(); M = read();
for(int i = 1 ; i < N ; ++i){
int a = read() , b = read();
ch[a].push_back(b); ch[b].push_back(a);
}
dfs(1 , 0); segt::init(1 , 1 , N); int x , y , z;
while(M--)
switch(read()){
case 1: LCT::access(read()); break;
case 2:
x = read(); y = read(); z = LCA(x , y);
printf("%d\n" , segt::qry(1 , 1 , N , dfn[x] , dfn[x]) + segt::qry(1 , 1 , N , dfn[y] , dfn[y])
- 2 * segt::qry(1 , 1 , N , dfn[z] , dfn[z]) + 1); break;
case 3: x = read(); printf("%d\n" , segt::qry(1 , 1 , N , dfn[x] , dfn[x] + sz[x] - 1));
}
return 0;
}

最新文章

  1. [转]-Dmaven.multiModuleProjectDirectory system propery is not set. 解决方案 适用于myeclipes 和 eclipes
  2. 新浪微博授权时出现&quot;关注 *** 的微博&quot;
  3. 导出excel的简单方法
  4. TensorFlow使用GPU
  5. asp.net网页上获取其中表格中的数据(爬数据)
  6. 新特技软件(Analyzer)添加新用户
  7. 分布式事务框架Seata及EasyTransaction架构的比对思考
  8. nginx 多级反向代理获取客户端真实IP
  9. windows下解决python输出utf-8中文
  10. Make Palindrome CodeForces - 600C(思维)
  11. android studio 查看大纲
  12. Bakery
  13. java中的this和super(构造函数)
  14. CIFAR和SVHN在各CNN论文中的结果
  15. ios规格证明
  16. 【转】MVC,MVP 和 MVVM 的图示
  17. java 当读取的结果为-1时候说明已经读取结束了
  18. Android提示框与通知的使用
  19. Oracle database精装版11gR2入门详细连接教程
  20. 【BZOJ 4198】[Noi2015]荷马史诗 哈夫曼编码

热门文章

  1. 启动hadoop报does not contain a valid host:port authority:node2_1:9000
  2. hdu2037 今年暑假不AC[贪心][区间调度问题]
  3. Vue/小程序/小程序云+Node+Mongo开发微信授权、支付和分享
  4. 【技术博客】Django+uginx+uwsgi框架的服务器部署
  5. 后台启动es head,关闭shell后es head自动关闭
  6. Spring的注解收集
  7. Spring Boot-JPA常用注解
  8. IntelliJ IDEA多屏后窗口不显示问题解决(用工具一键解决)
  9. Linux虚拟机:发布WebService接口出现异常,无法访问接口
  10. 005_Philippines之行准备