QWQ嘤嘤嘤

此题正规题解应该是边分治??或者是树剖(总之不是LCT)

但是我这里还是把它当成一个LCT题目来做

首先,这个题的重点还是在update上

因为有\(makeroot\)这个操作的存在,所以自然避免不了\(reverse\),而当\(reverse\)之后,会影响到每个点维护的值的时候,就需要同时维护两个相反的数组,在\(reverse\)的时候,直接\(swap\)

对于本题来说,我们对于一个点需要维护一个虚子树的\(maxdis\) (这里需要\(multiset\)来维护,因为access的时候,涉及到修改的问题)

一个到深度最浅的点的\(ans1\),到深度最深的点的\(ans2\),还有一个子\(splay\)的权值和

考虑转移,ans1的转移显然可以由\(ans1[ch[x][0]]\)转移而来(表示左子树内部的路径),其次,他还可以从\(min(fir(s[x]),ans1[ch[x][1]])+val[x]+val[ch[x][0]\)转移而来(表示从右子树或者虚子树开始的一条路径),如果当前点是合法的颜色,那么还可以从当前点开始的一条路径更新\(ans1\),而\(ans2\)直接全部反过来就好

void update(int x)
{
if (!x) return;
sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x];
ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]);
ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]);
//cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl;
if (col[x])
{
ans1[x]=min(ans1[x],sval[ch[x][0]]);
ans2[x]=min(ans2[x],sval[ch[x][1]]);
}
//lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs]));
//rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x]));
}

其他的话,就是一些小细节了,可以直接看代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set> using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 5e5+1e2;
//const int inf = 1e9; int lubenwei;
int ch[maxn][3];
int inf;
int fa[maxn],rev[maxn],ans1[maxn],ans2[maxn];
int sval[maxn],val[maxn];
int col[maxn];
int n,m;
multiset<int> s[maxn];
int tot;
int st[maxn]; int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
} bool notroot(int x)
{
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
} void reverse(int x)
{
swap(ans1[x],ans2[x]);
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
} int fir(int x)
{
//cout<<"ymh"<<endl;
if (s[x].size()>=1) return *(s[x].begin());
else return inf;
} void update(int x)
{
if (!x) return;
sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x];
ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]);
ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]);
//cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl;
if (col[x])
{
ans1[x]=min(ans1[x],sval[ch[x][0]]);
ans2[x]=min(ans2[x],sval[ch[x][1]]);
}
//lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs]));
//rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x]));
} void pushdown(int x)
{
if (rev[x])
{
if (ch[x][0]) reverse(ch[x][0]);
if (ch[x][1]) reverse(ch[x][1]);
rev[x]=0;
}
} void rotate(int x)
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y)) ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
} void splay(int x)
{
int y=x,cnt=0;
st[++cnt]=y;
while (notroot(y)) y=fa[y],st[++cnt]=y;
while (cnt) pushdown(st[cnt--]); while (notroot(x))
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y))
{
if (b==c) rotate(y);
else rotate(x);
}
rotate(x); }
///cout<<2<<endl;
update(x);
} void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
// cout<<1;
if (ch[x][1])s[x].insert(ans1[ch[x][1]]);
if (y && s[x].find(ans1[y])!=s[x].end()) s[x].erase(s[x].find(ans1[y]));
ch[x][1]=y;
update(x);
}
// cout<<"wancheng";
} void makeroot(int x)
{
access(x);//cout<<x<<endl;
splay(x);
reverse(x);
} int findroot(int x)
{
access(x);
splay(x);
while (ch[x][0])
{
pushdown(x);
x=ch[x][0];
}
return x;
} void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
} void link(int x,int y)
{
split(x,y);
if (findroot(y)!=x)
{
fa[x]=y;
s[y].insert(ans1[x]);
update(y);
}
}
int main()
{
memset(ans1,127/3,sizeof(ans1));
memset(ans2,127/3,sizeof(ans2));
inf = ans1[maxn-3];
n=read();
lubenwei=0;
tot=n;
for (int i=1;i<n;i++)
{
int x=read(),y=read();
val[++tot]=1;
link(x,tot);
link(y,tot);
}
m=read();
makeroot(1);
for (int i=1;i<=m;i++)
{
int opt=read();
int x=read();
if (opt==0)
{
makeroot(x);
col[x]^=1;
if (col[x]==1) lubenwei++;
else lubenwei--;
update(x);
}
if (opt==1)
{
makeroot(x);
if (!lubenwei) cout<<-1<<"\n";
else
if (col[x]) cout<<0<<"\n";
else cout<<ans1[x]<<"\n";
}
// cout<<"6deyanse:"<<col[x]<<endl;
}
return 0;
}

SPOJ2939 QTREE5(LCT维护子树信息)的更多相关文章

  1. 【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

    题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量 ...

  2. 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息

    题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...

  3. 【bzoj3510】首都 LCT维护子树信息(+启发式合并)

    题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...

  4. 【BZOJ3510】首都 LCT维护子树信息+启发式合并

    [BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...

  5. 共价大爷游长沙 lct 维护子树信息

    这个题目的关键就是判断 大爷所有可能会走的路 会不会经过询问的边. 某一条路径经过其中的一条边, 那么2个端点是在这条边的2测的. 现在我们要判断所有的路径是不是都经过 u -> v 我们以u为 ...

  6. bzoj3510 首都 LCT 维护子树信息+树的重心

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...

  7. $LCT$维护子树信息学习笔记

    \(LCT\)维护子树信息学习笔记 昨天\(FDF\)好题分享投了 \([ZJOI2018]\)历史 这题. 然后我顺势学学这个姿势. 结果调了一年...于是写个笔记记录一下. 基本原理 比较显然地, ...

  8. 【LCT维护子树信息】uoj207 共价大爷游长沙

    这道题思路方面就不多讲了,主要是通过这题学一下lct维护子树信息. lct某节点u的子树信息由其重链的一棵splay上信息和若干轻儿子子树信息合并而成. splay是有子树结构的,可以在rotate, ...

  9. 洛谷4219 BJOI2014大融合(LCT维护子树信息)

    QWQ 这个题目是LCT维护子树信息的经典应用 根据题目信息来看,对于一个这条边的两个端点各自的\(size\)乘起来,不过这个应该算呢? 我们可以考虑在LCT上多维护一个\(xv[i]\)表示\(i ...

  10. BZOJ4530[Bjoi2014]大融合——LCT维护子树信息

    题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数 ...

随机推荐

  1. kubebuilder实战之六:构建部署运行

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. 由Eratosthenes筛法演变出的一种素数新筛法

    这两天和walls老师交流讨论了一个中学竞赛题,我把原题稍作增强和变形,得到如下一个题: 从105到204这100个数中至少要选取多少个数才能保证选出的数中必有两个不是互素的? 我们知道最小的几个素数 ...

  3. Java特性和优势

    Java特性和优势 简单性 面向对象性 可移植性 高性能 分布式 动态性 多线程 安全性 健壮性

  4. CSS实用技巧(中)

    前言 我们经常使用CSS,但是却不怎么了解CSS,本文主要对vertical-align.BFC.position中开发过程不怎么注意的特性进行简要总结,从本文中,你将了解到以下内容: vertica ...

  5. 云效x钉钉:让研发工作更简单

    云效x钉钉:让研发工作更简单,奔走相告,云效&钉钉集成实现组织架构.成员同步以及消息通知啦! 我们知道云效致力于智能化.安全可追溯.高效.简单.灵活,「云效新一代企业级DevOps平台」阿里云 ...

  6. Python图像分割之区域增长法

    原文链接:https://blog.csdn.net/sgzqc/article/details/119682864 一.简介 区域增长法是一种已受到计算机视觉界十分关注的图像分割方法.它是以区域为处 ...

  7. 使用ogr裁剪矢量数据

    使用ogr裁剪矢量数据 由来: ​ 近期有个需求,内容是这样的:我们有两个矢量数据,现在要求以一个矢量文件为底板,按字段对另一个矢量文件进行分割,生成若干小的shpfile文件 分析: ​ 经过分析之 ...

  8. 383 day10缓冲流、转换流、序列化流

    day10[缓冲流.转换流.序列化流] 主要内容 缓冲流 转换流 序列化流 打印流 教学目标 [ ] 能够使用字节缓冲流读取数据到程序 [ ] 能够使用字节缓冲流写出数据到文件 [ ] 能够明确字符缓 ...

  9. 求1+2+…+n

    求 1+2+...+n ,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 示例 1: 输入: n = 3 输出: 6 示例 2: ...

  10. CodeForce-803C Maximal GCD(贪心数学)

    Maximal GCD CodeForces - 803C 现在给定一个正整数 n.你需要找到 k 个严格递增的正整数 a1, a2, ..., ak,满足他们的和等于 n 并且他们的最大公因数尽量大 ...