数据结构选讲 (更新中)

参考 smWCDay7 数据结构选讲2 by yyc

可能会补充的:

  • AT_cf17_final_j TreeMSTF2 Boruvka算法

目录

  • AT_cf17_final_j Tree MST
  • P5280 [ZJOI2019] 线段树

AT_cf17_final_j Tree MST

link
题意
给定一棵 n n n 个点的树,点有点权 w i w_i wi,边有边权。建立一张完全图 G G G,节点 u , v u, v u,v 之间的边长为 w u + w v + d i s ( u , v ) w_u + w_v + dis(u, v) wu+wv+dis(u,v) 。求 G G G M S T MST MST (最小生成树)的边权和。

  • n ≤ 2 × 1 0 5 , 1 ≤ w i ≤ 1 0 9 n \le 2 \times 10^5 ,1 \le w_i \le 10^9 n2×1051wi109

思路
前置指示:点分治

引理:边 e e e 在边集 E E E 的最小生成树中,则对于任意 E 0 ⊆ E E_0 ⊆ E E0E,e 也在边集 E 0 E_0 E0 的最小生成树中。
证明:考虑 kruskal
推论:将边分为若干组,分别求最小生成树,再合并求最小生成树,结果正确。

题目是说建立一张完全图然后求其的 M S T MST MST ,但是这样的边是 n 2 n^2 n2 级别的,考虑去掉一些多余的边,只保留有用的边。所以可以将完全图 G G G 分成很多个边集,分别求 M S T MST MST (不必强制联通),然后保留有用边,最后再综合求 M S T MST MST 就是答案了。
考虑 点分治,以重心为根,将树分成几个子树,那么就只用处理跨越重心的边即可。
d i s i dis_i disi 表示 点 i i i 到重心的距离,跨越重心的边 ( u , v ) (u,v) (u,v),边权是 w u + d i s u + w v + d i s v w_u + dis_u + w_v + dis_v wu+disu+wv+disv 。由于每个点 i i i 都要贡献至少一次 w i + d i s i w_i+dis_i wi+disi,另外一边肯定选最小的 w j + d i s j w_j+dis_j wj+disj ,所以我们只需要选择 w i + d i s i w_i + dis_i wi+disi 最小的点,让它和所有其他点连边,该菊花图就是最小生成树。(在同一棵子树内连了边也不影响结果,因为它们的边权比真实值要大 d i s u + d i s v > d i s u , v dis_u + dis_v \gt dis_{u,v} disu+disv>disu,v )。这样边的数量就减到了 n l o g n nlogn nlogn,总时间复杂度为 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

好像还有一种方法,要用到 Boruvka算法 ,后续可能会学……

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5;int idx,head[maxn];
struct EDGE{ int v,next; ll w; }e[maxn*2];
void Insert(int u,int v,ll w){e[++idx]={v,head[u],w};head[u]=idx;
}int siz[maxn],mxson[maxn],pot[maxn],tn;
bool vis[maxn];
void Dfs(int x,int fa){pot[++tn]=x,siz[x]=1,mxson[x]=0;for(int i=head[x];i;i=e[i].next){int v=e[i].v;if(!vis[v]&&v!=fa){Dfs(v,x);siz[x]+=siz[v];mxson[x]=max(mxson[x],siz[v]);}}
}int Get_root(int x){tn=0,Dfs(x,0);int root=0;for(int i=1;i<=tn;i++){mxson[pot[i]]=max(mxson[pot[i]],tn-siz[pot[i]]);if(!root||mxson[root]>mxson[pot[i]]) root=pot[i]; }return root;
}int id;
ll a[maxn],dis[maxn];
void Dfs2(int x,int fa){for(int i=head[x];i;i=e[i].next){int v=e[i].v;if(!vis[v]&&v!=fa){dis[v]=dis[x]+e[i].w;Dfs2(v,x);}}if(!id||a[x]+dis[x]<a[id]+dis[id]) id=x;
}int cnt;
struct EDGE2{ int u,v; ll w; }te[maxn*20];
void Solve(int rt){dis[rt]=0,id=0,Dfs2(rt,0);for(int i=1;i<=tn;i++)te[++cnt]={id,pot[i],a[id]+dis[id]+a[pot[i]]+dis[pot[i]]};vis[rt]=1;for(int i=head[rt];i;i=e[i].next){int v=e[i].v;if(!vis[v]) Solve(Get_root(v));}
}int fa[maxn];
int Find_fa(int x){ return fa[x]==x?x:fa[x]=Find_fa(fa[x]); }int main(){int n; cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<n;i++){int x,y,z; cin>>x>>y>>z;Insert(x,y,z),Insert(y,x,z);}Solve(Get_root(1));sort(te+1,te+cnt+1,[](EDGE2 a,EDGE2 b){ return a.w<b.w; });for(int i=1;i<=n;i++)fa[i]=i;ll ans=0;for(int i=1;i<=cnt;i++){int fx=Find_fa(te[i].u),fy=Find_fa(te[i].v);if(fx!=fy) fa[fy]=fx,ans+=te[i].w;}cout<<ans;return 0;
}

P5280 [ZJOI2019] 线段树

link
题意
维护线段树集合,初始时,集合中只有一棵 [ 1 , n ] [1, n] [1,n] 的空线段树。支持下列操作:

  • 将每棵线段树复制两份,其中一份执行区间覆盖。
  • 查询目前所有线段树中,有标记的节点个数。
  • n , m ≤ 1 0 5 n, m \le 10^5 n,m105

思路
看到题目,可以想到:线段树的个数是指数级别的,不可能单独地去维护每一棵线段树,但每棵线段树都是相同的,思考是否可以去用一棵线段树来维护,每次修改在上一次的基础上进行转移。 又发现一次修改中,不同的点的转移是不同的。
那就观察点的修改,总共可以分成五类:
picture

  • 白色:在 Modify 操作中,被半覆盖的点;
  • 深灰色:在 Modify 操作中,被全覆盖的点,并且能被遍历到;
  • 橙色:在 Modify 操作中,未被覆盖的点,并且可能可以得到 pushdown 来的标记;
  • 浅灰色:在 Modify 操作中,被全覆盖的点,并且不能被遍历到(深灰色点的儿子);
  • 黄色:在 Modify 操作中,未被覆盖的点,并且不可能得到 pushdown 来的标记(橙色点的儿子);

设个 D P DP DP 观察五种点的转移:记 f i , u f_{i,u} fi,u 表示到第 i i iModify 操作时, 在 2 i 2^i 2i 棵树中,点 u u u 被打了标记的个数;  g i , u g_{i,u} gi,u 表示到第 i i iModify 操作时, 在 2 i 2^i 2i 棵树中,有多少棵树满足根到结点 u u u 的路径上的点至少有一个标记。
转移如下:

  • 白色: f i , u = f i − 1 , u f_{i,u} = f_{i−1,u} fi,u=fi1,u g i , u = g i − 1 , u g_{i,u} = g_{i−1,u} gi,u=gi1,u
  • 深灰色: f i , u = f i − 1 , u + 2 i − 1 f_{i,u} = f_{i−1,u} + 2^{i-1} fi,u=fi1,u+2i1 g i , u = g i − 1 , u + 2 i − 1 g_{i,u} = g_{i−1,u} + 2^{i-1} gi,u=gi1,u+2i1
  • 橙色: f i , u = f i − 1 , u + g i − 1 , u f_{i,u} = f_{i−1,u} + g_{i-1,u} fi,u=fi1,u+gi1,u g i , u = 2 × g i − 1 , u g_{i,u} = 2 \times g_{i−1,u} gi,u=2×gi1,u
  • 浅灰色: f i , u = 2 × f i − 1 , u f_{i,u} = 2 \times f_{i−1,u} fi,u=2×fi1,u g i , u = g i − 1 , u + 2 i − 1 g_{i,u} = g_{i−1,u} + 2^{i-1} gi,u=gi1,u+2i1
  • 黄色: f i , u = 2 × f i − 1 , u f_{i,u} = 2 \times f_{i−1,u} fi,u=2×fi1,u g i , u = 2 × g i − 1 , u g_{i,u} = 2 \times g_{i−1,u} gi,u=2×gi1,u

每次修改暴力转移每个点是不可能的。但每次的白色,深灰色,橙色只有 O ( l o g n ) O(logn) O(logn) 个,可以暴力;浅灰色和黄色有 O ( n ) O(n) O(n) 个,可以用懒标记维护。还要维护 s u m u sum_u sumu 表示 u u u 子树中 f u f_u fu 的总和, s u m 1 sum_1 sum1 就是答案。
维护转移时有点细节(懒标记),注意多 p u s h d o w n pushdown pushdown 标记。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=998244353;struct TREE{ ll f,g,tagf,tagg,tagg2,sum; }tree[maxn*4];
void Build(int rt,int l,int r){tree[rt].tagf=tree[rt].tagg2=1;if(l==r) return;int mid=(l+r)>>1;Build(rt*2,l,mid),Build(rt*2+1,mid+1,r);
}void F_mul(int rt,ll k){ (tree[rt].f*=k)%=mod,(tree[rt].tagf*=k)%=mod,(tree[rt].sum*=k)%=mod; }
void G_add(int rt,ll k){ (tree[rt].g+=k)%=mod,(tree[rt].tagg+=k)%=mod; }
void G_mul(int rt,ll k){ (tree[rt].g*=k)%=mod,(tree[rt].tagg2*=k)%=mod,(tree[rt].tagg*=k)%=mod; }
void Pushdown(int rt){int ls=rt*2,rs=ls+1;if(tree[rt].tagf!=1) F_mul(ls,tree[rt].tagf),F_mul(rs,tree[rt].tagf),tree[rt].tagf=1;if(tree[rt].tagg2!=1) G_mul(ls,tree[rt].tagg2),G_mul(rs,tree[rt].tagg2),tree[rt].tagg2=1;if(tree[rt].tagg) G_add(ls,tree[rt].tagg),G_add(rs,tree[rt].tagg),tree[rt].tagg=0;
}
void Pushup(int rt){ tree[rt].sum=(tree[rt*2].sum+tree[rt*2+1].sum+tree[rt].f)%mod; }void Modify(int rt,int l,int r,int x,int y,ll z){//white, deep_grey, light_greyif(x<=l&&r<=y){//deep_grey(tree[rt].f+=z)%=mod,(tree[rt].g+=z)%=mod;F_mul(rt*2,2),G_add(rt*2,z); F_mul(rt*2+1,2),G_add(rt*2+1,z);//light_greyPushup(rt);return;}Pushdown(rt);int mid=(l+r)>>1;if(x<=mid) Modify(rt*2,l,mid,x,y,z);if(y>mid) Modify(rt*2+1,mid+1,r,x,y,z);Pushup(rt);
}void Modify2(int rt,int l,int r,int x,int y){//orange, yelloif(x<=l&&r<=y){//orange(tree[rt].f+=tree[rt].g)%=mod,(tree[rt].g*=2)%=mod;F_mul(rt*2,2),G_mul(rt*2,2); F_mul(rt*2+1,2),G_mul(rt*2+1,2);//yellowPushup(rt);return;}Pushdown(rt);int mid=(l+r)>>1;if(x<=mid) Modify2(rt*2,l,mid,x,y);if(y>mid) Modify2(rt*2+1,mid+1,r,x,y);Pushup(rt);
}ll pw[maxn];
int main(){int n,m; cin>>n>>m;pw[0]=1;for(int i=1;i<=m;i++)pw[i]=pw[i-1]*2%mod;Build(1,1,n);int cnt=0;while(m--){int opt; cin>>opt;if(opt==1){int x,y; cin>>x>>y; cnt++;Modify(1,1,n,x,y,pw[cnt-1]);if(x>1) Modify2(1,1,n,1,x-1);if(y<n) Modify2(1,1,n,y+1,n);}else cout<<tree[1].sum<<"\n";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/9767.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis学习之哨兵二

一、API 1.sentinel masters:展示被监控的主节点状态及相关的统计信息 2.sentinel master <master name>:展示指定的主节点的状态以及相关的统计信息 3.sentinel slaves <master name>:展示指定主节点的从节点状态以及相关的统计信息 4.sentinel sentinels <mas…

iperf 测 TCP 和 UDP 网络吞吐量

注&#xff1a;本文为 “iperf 测网络吞吐量” 相关文章合辑。 未整理去重。 使用 iperf3 监测网络吞吐量 Tom 王 2019-12-21 22:23:52 一 iperf3 介绍 (1.1) iperf3 是一个网络带宽测试工具&#xff0c;iperf3 可以擦拭 TCP 和 UDP 带宽质量。iperf3 可以测量最大 TCP 带宽…

Kafka 副本机制(包含AR、ISR、OSR、HW 和 LEO 介绍)

文章目录 Kafka 副本机制&#xff08;包含AR、ISR、OSR、HW 和 LEO 介绍&#xff09;1. 副本的基本概念2. 副本同步和一致性2.1 AR&#xff08;Assigned Replicas&#xff09;2.2 ISR&#xff08;In-Sync Replicas&#xff09;2.3 OSR&#xff08;Out-of-Sync Replicas&#xf…

java求职学习day18

常用的设计原则和设计模式 1 常用的设计原则&#xff08;记住&#xff09; 1.1 软件开发的流程 需求分析文档、概要设计文档、详细设计文档、编码和测试、安装和调试、维护和升级 1.2 常用的设计原则 &#xff08;1&#xff09;开闭原则&#xff08;Open Close Principle…

github制作静态网页

打开gihub并新建仓库 命名仓库&#xff1a;xxx.github.io 点击create repository进行创建 点击蓝色字体“creating a new file”创建文件 文件命名为index.html, 并编写html 右上角提交 找到setttings/pages&#xff0c;修改路径&#xff0c;点击保存&#xff0c;等…

shell脚本

Shell内容讲解 一、Shell 脚本基础概念 什么是 Shell 脚本&#xff1f; Shell 脚本是一个包含一系列 Shell 命令的文本文件&#xff0c;用于自动化执行任务&#xff08;如文件操作、程序调用、系统管理等&#xff09;。 Shell 类型 bash&#xff08;Bourne-Again Shell&#…

python:斐索实验(Fizeau experiment)

斐索实验&#xff08;Fizeau experiment&#xff09;是在1851年由法国物理学家阿曼德斐索&#xff08;Armand Fizeau&#xff09;进行的一项重要实验&#xff0c;旨在测量光在移动介质中的传播速度。这项实验的结果对当时的物理理论产生了深远的影响&#xff0c;并且在后来的相…

16.Word:石油化工设备技术❗【28】

目录 题目 NO1.2 NO3 NO4 题目 NO1.2 F12&#xff1a;另存为将“Word素材.docx”文件另存为“Word. docx”&#xff08;“docx”为文件扩展名&#xff09; 光标来到表格上方→插入→形状→新建画布→单击选中→格式→高度/宽度&#xff08;格式→大小对话框→取消勾选✔锁定…

计算机毕业设计Python+CNN卷积神经网络高考推荐系统 高考分数线预测 高考爬虫 协同过滤推荐算法 Vue.js Django Hadoop 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

DeepSeek-R1本地部署笔记

文章目录 效果概要下载 ollama终端下载模型【可选】浏览器插件 UIQ: 内存占用高&#xff0c;显存占用不高&#xff0c;正常吗 效果 我的配置如下 E5 2666 V3 AMD 590Gme 可以说是慢的一批了&#xff0c;内存和显卡都太垃圾了&#xff0c;回去用我的新设备再试试 概要 安装…

zyNo.19

哈希&#xff08;md5&#xff09;绕过问题 本质上是弱类型问题的延申 题型 登录的哈希验证 $a ! $b Md5($a) md5($b) 解决办法Md5绕过 var_dump ("0e123456" "0e4456789"); //true 0e545993274517709034328855841020//true 参考资料0e开头的哈希…

爬虫基础(一)HTTP协议 :请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…

XCTF - IllIntentions wp

做 ctf 每天都是踩坑的一天 文章目录 题目概述我的做法frida hook 题目概述 这道题本身逻辑不复杂&#xff0c;有一个 MainActivity 和三个二级 Activity IsThisTheRealOne, ThisIsTheRealOne, DefinitelyNotThis。主 activity 是空白页面&#xff0c;注册了一个 Receiver Sen…

LNMP架构

一、概述 LNMP架构是一种常用于搭建动态网站的服务器架构组合&#xff0c;其名称由以下四个组件的首字母缩写组成&#xff1a; Linux&#xff1a;操作系统。Linux具有开源、稳定、安全、高性能等特点&#xff0c;是服务器领域广泛使用的操作系统。它为其他组件提供了运行环境和…

【Unity3D】实现2D角色/怪物死亡消散粒子效果

核心&#xff1a;这是一个Unity粒子系统自带的一种功能&#xff0c;可将粒子生成控制在一个Texture图片网格范围内&#xff0c;并且粒子颜色会自动采样图片的像素点颜色&#xff0c;之后则是粒子编辑出消散效果。 Particle System1物体&#xff08;爆发式随机速度扩散10000个粒…

芯片AI深度实战:基础篇之langchain

基于ollama, langchain,可以构建一个自己的知识库&#xff0c;比如这个 Build Your Own RAG App: A Step-by-Step Guide to Setup LLM locally using Ollama, Python, and ChromaDB | HackerNoon 这是因为&#xff1a; 以上范例就实现了这样一个流程&#xff1a; 系列文章&…

mybatis(134/134)完结

一级缓存&#xff08;默认情况下开启&#xff09;同一个sqlsession中执行相同的查询语句走一级缓存 二级缓存 &#xff1a;同一个sqlsessionfactory&#xff0c;sqlsession关闭了才会将一级缓存提交到二级缓存中 外部编写的缓存 PageHelper插件&#xff1a;方便进行分页&#x…

C++,STL 简介:历史、组成、优势

文章目录 引言一、STL 的历史STL 的核心组成三、STL 的核心优势四、结语进一步学习资源&#xff1a; 引言 C 是一门强大且灵活的编程语言&#xff0c;但其真正的魅力之一在于其标准库——尤其是标准模板库&#xff08;Standard Template Library, STL&#xff09;。STL 提供了…

不背单词快捷键(不背单词键盘快捷键)

文章目录 不背单词快捷键 不背单词快捷键 ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ    …

EasyExcel写入和读取多个sheet

最近在工作中&#xff0c;作者频频接触到Excel处理&#xff0c;因此也对EasyExcel进行了一定的研究和学习&#xff0c;也曾困扰过如何处理多个sheet&#xff0c;因此此处分享给大家&#xff0c;希望能有所帮助 目录 1.依赖 2. Excel类 3.处理Excel读取和写入多个sheet 4. 执…