#轻重链剖分,线段树#洛谷 3703 [SDOI2017]树点涂色
分析
可以发现相同的颜色一定组成一个连通块。
那么操作2就相当于 \(f_x+f_y-2*f_{lca}+1\)
操作3就相当于询问 \(f\) 的最大值。
最关键的就是操作1,考虑往上跳,在同颜色与同重链之间选深度较大的一个。
那么就是要把重链上的这一段染成新的颜色,在线段树上维护颜色以及f值。
现在的链顶的子树所有的 \(f\) 都要减1,并且如果之前子树的点操作过那么就要撤销回来。
然后如果当前点不是原颜色的链底,那么当前点的那一子节点的子树就要整体加一。
颜色的链顶和链底可以在修改的时候动态维护,这样时间复杂度就是两个 \(\log\) 的
代码
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;
const int N=100011; struct node{int y,next;}e[N<<1]; vector<int>K[N];
int as[N],dep[N],siz[N],tot,ext,n,m,et=1,fat[N],big[N],Top[N],dfn[N],rfn[N],nfd[N];
int lazy[N<<2],w[N<<2],col[N<<2],ct[N<<1],cb[N<<1];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void dfs1(int x,int fa){
dep[x]=dep[fa]+1,siz[x]=1,fat[x]=fa;
for (int i=as[x],SIZ=-1;i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x),siz[x]+=siz[e[i].y];
if (SIZ<siz[e[i].y]) big[x]=e[i].y,SIZ=siz[e[i].y];
}
}
void dfs2(int x,int linp){
dfn[x]=++tot,nfd[tot]=x,Top[x]=linp;
if (!big[x]) return;
dfs2(big[x],linp),K[x].push_back(dfn[big[x]]);
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x])
dfs2(e[i].y,e[i].y),K[x].push_back(dfn[e[i].y]);
}
int max(int a,int b){return a>b?a:b;}
void build(int k,int l,int r){
if (l==r){
w[k]=dep[nfd[l]],col[k]=nfd[l];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
w[k]=max(w[k<<1],w[k<<1|1]);
}
int lca(int x,int y){
for (;Top[x]!=Top[y];x=fat[Top[x]])
if (dep[Top[x]]<dep[Top[y]]) x^=y,y^=x,x^=y;
return dep[x]<dep[y]?x:y;
}
void ptag(int k,int z){w[k]+=z,lazy[k]+=z;}
void update(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y) {ptag(k,z); return;}
int mid=(l+r)>>1;
if (lazy[k]){
ptag(k<<1,lazy[k]);
ptag(k<<1|1,lazy[k]);
lazy[k]=0;
}
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
w[k]=max(w[k<<1],w[k<<1|1]);
}
void upd(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y) {col[k]=z; return;}
int mid=(l+r)>>1;
if (y<=mid) upd(k<<1,l,mid,x,y,z);
else if (x>mid) upd(k<<1|1,mid+1,r,x,y,z);
else upd(k<<1,l,mid,x,mid,z),upd(k<<1|1,mid+1,r,mid+1,y,z);
}
int query_col(int k,int l,int r,int x){
if (l==r) return col[k];
int mid=(l+r)>>1;
if (x<=mid) return max(col[k],query_col(k<<1,l,mid,x));
else return max(col[k],query_col(k<<1|1,mid+1,r,x));
}
int query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return w[k];
int mid=(l+r)>>1;
if (lazy[k]){
ptag(k<<1,lazy[k]);
ptag(k<<1|1,lazy[k]);
lazy[k]=0;
}
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return max(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
void Update(int x){
ct[++ext]=1,cb[ext]=x;
for (int lst=0,Ct=0;x;x=fat[lst]){
int col=query_col(1,1,n,dfn[x]);
int w=query(1,1,n,dfn[x],dfn[x]);
if (x!=cb[col]){
int now=nfd[*(--upper_bound(K[x].begin(),K[x].end(),dfn[cb[col]]))];
if (now!=lst) update(1,1,n,dfn[now],rfn[now],1),Ct=now;
}
if (dep[ct[col]]<dep[Top[x]]){
update(1,1,n,dfn[Top[x]],rfn[Top[x]],1-w);
upd(1,1,n,dfn[Top[x]],dfn[x],ext);
if (lst) update(1,1,n,dfn[lst],rfn[lst],w-1);
lst=Top[x];
}else{
update(1,1,n,dfn[ct[col]],rfn[ct[col]],1-w);
upd(1,1,n,dfn[ct[col]],dfn[x],ext);
if (lst) update(1,1,n,dfn[lst],rfn[lst],w-1);
lst=ct[col],ct[col]=Ct;
}
}
}
int main(){
ext=n=iut(),m=iut();
for (int i=1;i<n;++i){
int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
for (int i=1;i<=n;++i) ct[i]=cb[i]=i;
dfs1(1,0),dfs2(1,1),build(1,1,n);
for (int i=1;i<=n;++i) rfn[i]=dfn[i]+siz[i]-1;
for (int i=1;i<=m;++i){
int opt=iut(),x=iut();
switch (opt){
case 1:{
Update(x);
break;
}
case 2:{
int y=iut(),Lca=lca(x,y),t0,t1,t2;
t0=query(1,1,n,dfn[x],dfn[x]);
t1=query(1,1,n,dfn[y],dfn[y]);
t2=query(1,1,n,dfn[Lca],dfn[Lca]);
print(t0+t1-t2*2+1),putchar(10);
break;
}
case 3:{
print(query(1,1,n,dfn[x],rfn[x])),putchar(10);
break;
}
}
}
return 0;
}
#轻重链剖分,线段树#洛谷 3703 [SDOI2017]树点涂色的更多相关文章
- 洛谷3703 SDOI2017树点涂色(LCT+线段树+dfs序)
又一道好题啊qwqqqq 一开始看这个题,还以为是一个树剖的什么毒瘤题目 (不过的确貌似可以用树剖啊) qwq这真是一道\(LCT\)维护颜色的好题 首先,我们来一个一个操作的考虑. 对于操作\(1\ ...
- 洛谷3703 [SDOI2017] 树点染色 【LCT】【线段树】
题目分析: 操作一很明显等价于LCT上的access操作,操作二是常识,操作三转化到dfs序上求最大值也是常识.access的时候顺便在线段树中把对应部分-1,把右子树的子树+1即可. 代码: #in ...
- 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)
洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...
- 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)
2020/4/30 15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...
- 洛谷1087 FBI树 解题报告
洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...
- 洛谷P3018 [USACO11MAR]树装饰Tree Decoration
洛谷P3018 [USACO11MAR]树装饰Tree Decoration树形DP 因为要求最小,我们就贪心地用每个子树中的最小cost来支付就行了 #include <bits/stdc++ ...
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- 洛谷 P3781 - [SDOI2017]切树游戏(动态 DP+FWT)
洛谷题面传送门 SDOI 2017 R2 D1 T3,nb tea %%% 讲个笑话,最近我在学动态 dp,wjz 在学 FWT,而我们刚好在同一天做到了这道题,而这道题刚好又是 FWT+动态 dp ...
- 洛谷 P3714 - [BJOI2017]树的难题(点分治)
洛谷题面传送门 咦?鸽子 tzc 竟然来补题解了?incredible( 首先看到这样类似于路径统计的问题我们可以非常自然地想到点分治.每次我们找出每个连通块的重心 \(x\) 然后以 \(x\) 为 ...
- 洛谷P3830 随机树(SHOI2012)概率期望DP
题意:中文题,按照题目要求的二叉树生成方式,问(1)叶平均深度 (2)树平均深度 解法:这道题看完题之后完全没头绪,无奈看题解果然不是我能想到的qwq.题解参考https://blog.csdn.ne ...
随机推荐
- SQL Server初体验
概述 基于SQL Server 2019 Developer免费版搭建一个本地的开发环境. 下载安装 安装文件下载地址:https://www.microsoft.com/zh-cn/sql-serv ...
- 【WiFi开发全攻略】WIFI基础知识大全
[WiFi开发全攻略]WIFI基础知识大全 1. Wi-Fi起源 现在我们大家对Wi-Fi肯定都不陌生,无论是笔记本,手机,智能电视,都离不开Wi-Fi.目前我们一般用的都是Wi-Fi5,Wi-Fi6 ...
- Spring使用注解方式进行事务管理
目录 使用步骤: 步骤一.在spring配置文件中引入tx:命名空间 步骤二.具有@Transactional 注解的bean自动配置为声明式事务支持 步骤三.在接口或类的声明处 ,写一个@Trans ...
- Java package(包) +import 关键字(1)
Java 包(package) 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间. 包的作用 1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2.如同文件夹一样, ...
- windows编译ZLMediaKit流媒体服务webrtc
环境说明 ZLMediaKit编译需要的软件 visual studio 2022 cmake 3.29.0-rc2 OpenSSL 1.1.1w(不想踩坑的话安装这个版本) libsrtp 2.6. ...
- [VueJsDev] 基础知识 - asyncTool.js异步执行工具
[VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html asyncTool.js 异步执行工具 ::: detail ...
- 基于泰凌微2.4G私有协议TLSR8359的遥控器解决方案之源码解析
一 2.4G私有协议 在无线遥控和远距离无线通信领域,2.4G私有协议有着天然的优势.成本低,发射功率大,功耗低.这让它在远距离无线遥控飞机,遥控车等领域有着广泛的应用.基于TLSR8359市场上广泛 ...
- 麦克风阵列技术-beaforming开源算法源码分析
概述 在音频前端处理算法中,beamforming算法是一个无法绕过的存在,随着AI技术的广泛发展,前端语音技术的需求也在呈现个性化的动态范围.作为一个深耕音频算法多年的老兵,发现站在巨人的肩膀上 ...
- SVN 提交文件报错:svn: E155015: Aborting commit:
svn 提交文件报错: svn: E155015: Commit failed (details follow): svn: E155015: Aborting commit: '文件名称' rema ...
- 广汽传祺E9上市,3DCAT实时云渲染助力线上3D高清看车体验
2023年5月21日,中国智电新能源旗舰MPV--广汽传祺智电新能源E9在北京人民大会堂举办上市发布会. 发布会现场(图源官方) 为了让更多的消费者能够在线上感受到广汽传祺E9的魅力,3DCAT实时渲 ...