热门标签 | 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;
}

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



推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 题目描述Takuru是一名情报强者,所以他想利用他强大的情报搜集能力来当中间商赚差价。Takuru的计划是让Hinae帮他去市场上买一个商品,然后再以另一个价格卖掉它。Takur ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 796.[APIO2012]派遣在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为Master。 ... [详细]
  • P2765魔术球问题这道题的思路实在是太罕见了,所以发一篇blog从某一新放入的球开始看起1.放入原来的柱子上2.放入新的柱子并将每个点进行拆点࿰ ... [详细]
  • DescriptionclickmeSolution套路的状压期望DP题。。。考虑倒退期望:设fi,jrolepresentationstyleposi ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • APUE学习笔记可变参数(apue中错误输出函数的实现)
    2019独角兽企业重金招聘Python工程师标准voiderr_dump(constchar*fmt,){va_listap;va_start(ap,fmt);初始化 ... [详细]
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社区 版权所有