热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【CF1628E】GroceriesinMeteorTown(Kruskal重构树+线段树)

题目链接给定一棵\(n\)个点的树,每条边有一个边权,初始所有点都是黑点。\(q\)次操作,分为三种:将编号在\([l,r]\)范围内的点改成白点;将编号在\([l,r]\)范围内

题目链接



  • 给定一棵 \(n\) 个点的树,每条边有一个边权,初始所有点都是黑点。

  • \(q\) 次操作,分为三种:将编号在 \([l,r]\) 范围内的点改成白点;将编号在 \([l,r]\) 范围内的点改成黑点;询问从一个点出发到所有白点的简单路径上的最大边权。

  • \(2\le n,q\le3\times10^5\)


Kruskal 重构树

询问从一个点到所有白点的简单路径上的最大边权,其实就是问由这个点和所有白点构成的虚树上的最大边权。

也就是询问一个最小的权值,满足仅保留小于等于这个值的边时这个点能与所有白点连通。

这其实就是求这些点在 Kruskal 重构树中的 \(\operatorname{LCA}\) 的权值。

要求若干点 \(\operatorname{LCA}\),实际上只要知道其中 dfs 序最小的点和 dfs 序最大的点,求出它们的 \(\operatorname{LCA}\) 即可。

所以用一棵线段树维护最小 dfs 序和最大 dfs 序。

事先预处理出每个节点表示的区间内所有 dfs 序的最小值和最大值,这样区间染白的时候就可以直接调用信息。


代码:\(O(n\log n)\)

#include
#define Tp template
#define Ts template
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 300000
#define LN 19
using namespace std;
namespace FastIO
{
#define FS 100000
#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('\n');}
I void NA() {pc('-'),pc('1'),pc('\n');}
}using namespace FastIO;
int n;struct line {int x,y,v;bool operator <(Cn line& o) Cn {return vnamespace K//Kruskal重构树
{
int ct,V[N<<1],S[N<<1][2],d,dfn[N<<1],fac[N<<1],D[N<<1],f[N<<1][LN+1];
int fa[N+5];int Fa(CI x) {return fa[x]?fa[x]=Fa(fa[x]):x;}//并查集
void dfs(CI x,CI p=0) {D[x]=D[f[x][0]=p]+1,fac[dfn[x]=++d]=x,x>n&&(dfs(S[x][0],x),dfs(S[x][1],x),0);}//dfs
I void Bd()//建树+预处理
{
RI i,j;for(sort(s+1,s+n),ct=n,i=1;i^n;++i) V[++ct]=s[i].v,fa[S[ct][0]=Fa(s[i].x)]=fa[S[ct][1]=Fa(s[i].y)]=ct;//Kruskal建树
for(dfs(ct),j=1;j<=LN;++j) for(i=1;i<=ct;++i) f[i][j]=f[f[i][j-1]][j-1];//倍增预处理
}
I int LCA(RI x,RI y)//倍增LCA
{
RI i;for(D[x]>i&1&&(x=f[x][i]);if(x==y) return x;
for(i=0;f[x][i]^f[y][i];++i);for(--i;~i;--i) f[x][i]^f[y][i]&&(x=f[x][i],y=f[y][i]);return f[x][0];
}
}
class SegmentTree//线段树
{
private:
#define PT RI l=1,RI r=n,RI o=1
#define LT l,u,o<<1
#define RT u+1,r,o<<1|1
#define PU(o) (Mn[o]=min(Mn[o<<1],Mn[o<<1|1]),Mx[o]=max(Mx[o<<1],Mx[o<<1|1]))
#define PD(o) (~P[o]&&(T(o<<1,P[o]),T(o<<1|1,P[o]),P[o]=-1))
#define T(o,v) ((P[o]=v)?(Mn[o]=Mn0[o],Mx[o]=Mx0[o]):(Mn[o]=1e9,Mx[o]=0))//染色修改
int P[N<<2],Mn[N<<2],Mx[N<<2],Mn0[N<<2],Mx0[N<<2];
public:
void Bd(PT)
{
if(Mn[o]=1e9,Mx[o]=0,l==r) return (void)(Mn0[o]=Mx0[o]=K::dfn[l]);RI u=l+r>>1;Bd(LT),Bd(RT);
Mn0[o]=min(Mn0[o<<1],Mn0[o<<1|1]),Mx0[o]=max(Mx0[o<<1],Mx0[o<<1|1]);//预处理区间内最小值和最大值
}
void U(CI L,CI R,CI v,PT)//区间染色
{
if(L<=l&&r<=R) return (void)T(o,v);RI u=l+r>>1;PD(o);L<=u&&(U(L,R,v,LT),0),R>u&&(U(L,R,v,RT),0),PU(o);
}
I int G(CI x) Cn//加入x询问
{
RI mn=min(Mn[1],K::dfn[x]),mx=max(Mx[1],K::dfn[x]);return K::V[K::LCA(K::fac[mn],K::fac[mx])];//询问dfs序最小和最大的点的LCA
}
}S;
int main()
{
RI Qt,i;for(read(n,Qt),i=1;i^n;++i) read(s[i].x,s[i].y,s[i].v);K::Bd();
RI op,x,y,t;S.Bd();W(Qt--) switch(read(op),op)
{
case 1:read(x,y),S.U(x,y,1);break;case 2:read(x,y),S.U(x,y,0);break;
case 3:read(x),(t=S.G(x))?writeln(t):NA();break;
}return clear(),0;
}

败得义无反顾,弱得一无是处



推荐阅读
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 使用QT构建基础串口辅助工具
    本文详细介绍了如何利用QT框架创建一个简易的串口助手应用程序,包括项目的建立、界面设计与编程实现、运行测试以及最终的应用程序打包。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 本文介绍了在Linux环境下如何有效返回命令行状态、上一级目录及快速查找头文件和函数定义的方法。包括处理长时间运行命令、编辑器退出技巧、目录导航以及文件搜索策略。 ... [详细]
  • 本文是对《敏捷软件开发:原则、模式与实践》一书的深度解析,书中不仅探讨了敏捷方法的核心理念及其应用,还详细介绍了面向对象设计的原则、设计模式的应用技巧及UML的有效使用。 ... [详细]
  • 函子(Functor)是函数式编程中的一个重要概念,它不仅是一个特殊的容器,还提供了一种优雅的方式来处理值和函数。本文将详细介绍函子的基本概念及其在函数式编程中的应用,包括如何通过函子控制副作用、处理异常以及进行异步操作。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • Java 中的十进制样式 getZeroDigit()方法,示例 ... [详细]
  • 本文介绍了一种方法,通过使用Python的ctypes库来调用C++代码。具体实例为实现一个简单的加法器,并详细说明了从编写C++代码到编译及最终在Python中调用的全过程。 ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 本文详细介绍了如何在循环双链表的指定位置插入新元素的方法,包括必要的步骤和代码示例。 ... [详细]
  • 线段树详解与实现
    本文详细介绍了线段树的基本概念及其在编程竞赛中的应用,并提供了一个具体的线段树实现代码示例。 ... [详细]
  • PHP面试题精选及答案解析
    本文精选了新浪PHP笔试题及最新的PHP面试题,并提供了详细的答案解析,帮助求职者更好地准备PHP相关的面试。 ... [详细]
author-avatar
洋紫儿__来丶了
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有