P3979 遥远的国度

P3979 遥远的国度 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

问题描述:换根,路径修改,查询以某一个节点为根的最小值。

思路:树链剖分。

注意:设置的INF0x3f3f3f3f只会有30分,设置成int型最大值以上才能过。

x和y路径上的修改

  • 如果x和y的重链头父亲节点不一样,就让深度更大的那条链进行修改。

  • 如果x和y在同一条链上,则按照顺序进行修改。

void treechange(int x, int y, int k) { while(top[x] != top[y]) {if(dep[ top[x]] < dep[ top[y]]) swap(x,y);modify(1, dfn[ top[x]], dfn[x], k);x = fa[ top[x]];}if(dep[x] > dep[y]) swap(x,y);modify(1, dfn[x], dfn[y], k);
}

查询以x为根的子树中的最小值

树链剖分(附带LCA和换根)——基于dfs序的树上优化_dazha6157的博客-CSDN博客

// u 到 root路径上 与u相挨着的节点v的子树
int find_adj(int u, int rt) {// 从深度大的开始跳,往上跳while(top[u] != top[rt]) {if(dep[ top[u]] < dep[ top[rt]]) swap(u,rt);// 如果 root是u所在重链的父亲节点,那么直接返回即可if(fa[ top[u]] == rt) return top[u];u = fa[ top[u]];}// 让root深度最浅if(dep[u] < dep[rt]) swap(u, rt);return son[rt];
}
// 同上
LL nodemi(int u) {if(root == u) return query(1,1,n);else {int lac = lca(u, root);if(lac != u) return query(1, dfn[u], dfn[u] + siz[u] - 1);else {int adju = find_adj(u, root);int mi = INF;int L = dfn[adju] - 1, R = dfn[adju] + siz[adju];int mm1 = INF, mm2 = INF;if(L >= 1) mm1 = query(1, 1,L);if(R <= n) mm2 = query(1,R,n);mi = min(mm1, mm2);return mi;}}
}

AC代码:

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <random>
#include <climits>
#include <sstream>
#include <numeric>
#include <stdio.h>
#include <functional>
#include <bitset>
#include <algorithm>
using namespace std;// #define Multiple_groups_of_examples
#define IOS std::cout.tie(0);std::cin.tie(0)->sync_with_stdio(false);
#define dbgnb(a) std::cout << #a << " = " << a << '\n';
#define dbgtt cout<<" !!!test!!! "<<endl;
#define rep(i,x,n) for(int i = x; i <= n; i++)#define all(x) (x).begin(),(x).end()
#define pb push_back
#define vf first
#define vs secondtypedef long long LL;
#define int long long 
typedef pair<int,int> PII;// const int INF = 0x3f3f3f3f;
const int INF = INT_MAX;
const int N = 5e5 + 21;int fa[N], dep[N], siz[N], son[N], top[N], dfn[N], rnk[N];
int h[N], e[N], ne[N], w[N], dist[N], idx,cnt;
int p;
void inpfile();void add(int u, int v) {e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}
/* -------------------- 树链剖分 两次dfs -----------------------------------------------------------*/// 找出 fa dep siz son
void dfs1(int u) {// if(dep[u]) son[u] = -1; // 重儿子设置为-1siz[u] = 1; // 当前u节点大小为1(它本身for(int i = h[u]; ~i; i = ne[i]) {int y = e[i];if(y == fa[u]) continue; // ** if(!dep[ y]) { // 如果深度没有,则可以接着往下遍历dep[ y] = dep[u] + 1; // 求出深度fa[ y] = u; // 为y设置父亲节点dfs1(y); // 递归 ysiz[u] += siz[ y]; // 当前节点u增加子节点个数if(son[u] == -1 || siz[ y] > siz[ son[u]]) son[u] = y; // 更新重儿子}}
}// 求出 top dfn rnk
void dfs2(int u, int t) {top[u] = t; // 设置节点u的顶部节点为tcnt++;dfn[u] = cnt; // 在线段树中的编号rnk[cnt] = u; // DFS序对应的节点编号if(son[u] == -1) return ; // 如果son[u] = -1,表示是叶子节点dfs2(son[u], t); // 优先对重儿子进行DFS,保证同一条重链上的点DFS序连续for(int i = h[u]; ~i; i = ne[i]) {int y = e[i];// 当不是u的重儿子,也不是u的父亲节点// 那就是新的重链if(y != son[u] && y != fa[u]) dfs2(y, y); }
}// 求lca
int lca(int u, int v) {// 当两个点的重链顶点不一样时,表示是两个不同的重链// 深度大的向上跳// 跳到重链顶点的父亲节点while(top[u] != top[v]) {if(dep[ top[u]] > dep[ top[v]]) {u = fa[ top[u]];} else {v = fa[ top[v]];}}return dep[u] > dep[v] ? v : u;
}/* -------------------- 线段树 [ 区间修改 板子 ] --------------------------------------------------*/
// ( 裸线段树:树中点映射到线段树重
struct SegTree {int l,r;LL mi,lz;
}tr[N << 2];
inline int ls(int u) {return u << 1; }
inline int rs(int u) {return u << 1 | 1; }
void pushup(int u) {tr[u].mi = min(tr[ls(u)].mi, tr[rs(u)].mi);
}
void pushdown(int u) {auto &root = tr[u], &left = tr[ls(u)], &right = tr[rs(u)];if(root.lz) {left.lz = root.lz; left.mi = root.mi;right.lz = root.lz; right.mi = root.mi;root.lz = 0;}
}
void build(int u, int l, int r) {if(l == r) tr[u] = {l,r,w[r],0};else {tr[u] = {l,r,INF,0};int mid = l + r >> 1;build(ls(u), l, mid), build(rs(u), mid + 1, r);pushup(u);}
}
void modify(int u, int l, int r, int k) {if(tr[u].l >= l && tr[u].r <= r) {tr[u].lz = 1;tr[u].mi = k;return ;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;if(l <= mid) modify(ls(u),l,r,k);if(r > mid) modify(rs(u), l, r,k);pushup(u);
}
LL query(int u, int l, int r) {if(tr[u].l >= l && tr[u].r <= r) {return tr[u].mi;}int mid = tr[u].l + tr[u].r >> 1;LL mi = INF;pushdown(u);if(l <= mid) mi = query(ls(u), l,r);if(r > mid) mi = min(mi, query(rs(u),l,r));return mi;
}
/* -------------------- 树链剖分 ------------------------------------------------------------------------*/void treechange(int x, int y, int k) { while(top[x] != top[y]) {if(dep[ top[x]] < dep[ top[y]]) swap(x,y);modify(1, dfn[ top[x]], dfn[x], k);x = fa[ top[x]];}if(dep[x] > dep[y]) swap(x,y);modify(1, dfn[x], dfn[y], k);
}
/*----------------------------- 换根操作 ------------------------------------------------------------*/
int root, n,m;/*--------------------------------以root为根的增添,查询 ----------------------------------------------*/
// u 到 root路径上 与u相挨着的节点v的子树
int find_adj(int u, int rt) {// 从深度大的开始跳,往上跳while(top[u] != top[rt]) {if(dep[ top[u]] < dep[ top[rt]]) swap(u,rt);// 如果 root是u所在重链的父亲节点,那么直接返回即可if(fa[ top[u]] == rt) return top[u];u = fa[ top[u]];}// 让root深度最浅if(dep[u] < dep[rt]) swap(u, rt);return son[rt];
}
// 同上
LL nodemi(int u) {if(root == u) return query(1,1,n);else {int lac = lca(u, root);if(lac != u) return query(1, dfn[u], dfn[u] + siz[u] - 1);else {int adju = find_adj(u, root);int mi = INF;int L = dfn[adju] - 1, R = dfn[adju] + siz[adju];int mm1 = INF, mm2 = INF;if(L >= 1) mm1 = query(1, 1,L);if(R <= n) mm2 = query(1,R,n);mi = min(mm1, mm2);return mi;}}
}
int a[N];
void solve() {memset(h, -1, sizeof(h));cin>>n>>m;// root = 1;for(int i = 1; i < n; ++i) {int u,v; cin>>u>>v;add(u,v);add(v,u);}for(int i = 1; i <= n; ++i) cin>>a[i];cin>>root;// dbgtt/* ------- dfs * 2-------------------------------------*/dfs1(root);dfs2(root, root);/* ------- 将对应的在线段树中的位置和值进行设置 ---------*/for(int i = 1; i <= n; ++i) w[ dfn[i]] = a[i];// for(int i = 1; i <= n; ++i) cout<<dfn[i]<<endl;/* ------- 建树 ---------*/build(1,1,n);/* --------- 查询 -----------------------------------*/while(m--) {int opt, x,y,v; cin>>opt;if(opt == 1) {cin>>x;root = x;} else if(opt == 2) {cin>>x>>y>>v;treechange(x,y,v);} else {cin>>x;cout<<nodemi(x)<<endl;}}}
signed main()
{#ifdef Multiple_groups_of_examplesint T; cin>>T;while(T--)#endifsolve();return 0;
}
void inpfile() {#define mytest#ifdef mytestfreopen("ANSWER.txt", "w",stdout);#endif
}

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

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

相关文章

【仿写tomcat】四、解析http请求信息,响应给前端,HttpServletRequest、HttpServletResponse的简单实现

思考 在解析请求之前我们要思考一个问题&#xff0c;我们解析的是其中的哪些内容&#xff1f; 对于最基本的实现&#xff0c;当然是请求类型&#xff0c;请求的url以及请求参数&#xff0c;我们可以根据请求的类型作出对应的处理&#xff0c;通过url在我们的mapstore中找到se…

使用struct解析通达信本地Lday日线数据

★★★★★博文原创不易&#xff0c;我的博文不需要打赏&#xff0c;也不需要知识付费&#xff0c;可以白嫖学习编程小技巧&#xff0c;喜欢的老铁可以多多帮忙点赞&#xff0c;小红牛在此表示感谢。★★★★★ 在Python中&#xff0c;struct模块提供了二进制数据的打包和解包…

Java 项目日志实例:Log4j2

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ Apache Log4j 2 是对 Log4j 的升级&#xff0c;与其前身 Log4j 1.x 相比有了显着的改进&#xff0c;并提供了许多 Logback 可用的改进&#xff0c;同时支持 JCL 以及 SLF4J…

毫米波雷达成像论文阅读笔记: IEEE TPAMI 2023 | CoIR: Compressive Implicit Radar

原始笔记链接&#xff1a;https://mp.weixin.qq.com/s?__bizMzg4MjgxMjgyMg&mid2247486680&idx1&snedf41d4f95395d7294bc958ea68d3a68&chksmcf51be21f826373790bc6d79bcea6eb2cb3d09bb1860bba0af0fd5e60c448ca006976503e460#rd ↑ \uparrow ↑点击上述链接即…

前端开发,怎么解决浏览器兼容性问题? - 易智编译EaseEditing

解决浏览器兼容性问题是前端开发中常见的挑战之一。不同的浏览器可能对网页元素的渲染和功能支持有所不同&#xff0c;因此需要采取一些策略来确保您的网页在不同浏览器上都能正常运行和呈现。以下是一些解决浏览器兼容性问题的方法和策略&#xff1a; 使用CSS Reset&#xff…

Nuxt3_1_路由+页面+组件+资源+样式 使用及实例

1、 简介 1.1 开发必备 node版本 v16.10.0 我使用的是16.14.0编辑器推荐使用Volar Extension 的VS code插件Terminal 运行nuxt指令 1.2 环境搭建 安装项目&#xff1a; npx nuxilatest init [first_nuxt3]进入项目目录&#xff1a; cd [first_nuxt3]安装依赖&#xff1a;n…

Blazor前后端框架Known-V1.2.13

V1.2.13 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazo…

探索Perfetto:开源性能追踪工具的未来之光

探索Perfetto&#xff1a;开源性能追踪工具的未来之光 1. 引言 A. 介绍Perfetto的背景和作用 随着移动应用、桌面软件和嵌入式系统的不断发展&#xff0c;软件性能优化变得愈发重要。在这个背景下&#xff0c;Perfetto作为一款开源性能追踪工具&#xff0c;日益引起了开发者…

BC108 矩阵交换

描述 KiKi有一个矩阵&#xff0c;他想知道经过k次行变换或列变换后得到的矩阵。请编程帮他解答。 输入描述 第一行包含两个整数n和m&#xff0c;表示一个矩阵包含n行m列&#xff0c;用空格分隔。 (1≤n≤10,1≤m≤10) 从2到n1行&#xff0c;每行输入m个整数&#xff08;范围-…

小程序扫描二维码获取网址,通过Jsoup进行解析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、Jsoup是什么&#xff1f; 二、使用步骤 1.引入库 2.读入数据 总结 前言 vx开发小程序使用扫一扫时不同二维码展示的东西不一样,需要进行解析 提示&a…

管理类联考——逻辑——真题篇——按知识分类——汇总篇——一、形式逻辑——联选言

文章目录 第五节 联言+选言-摩根定理-非(A或B)=非A且非B,非(A且B)=非A或非B真题(2013-49)-联言+选言-摩根定理-非(A或B)=非A且非B,非(A且B)=非A或非B真题(2012-33)-联言+选言-摩根定理-非(A或B)=非A且非B,非(A且B)=非A或非B真题(2014-42)-联言+选言-摩根定理-非(A或B…

nodejs实现http与https服务;同时处理proxy代理的解决方案

// nodejs服务提供的http协议示例 const http require(http); const server http.createServer((req, res) > {res.writeHead(200, { Content-Type: text/html;charsetutf8 });res.end(Date.now() > http访问成功8080) }); server.listen(8080, () > {console.lo…

java云智慧工地管理平台系统源码

智慧工地将“互联网”的理念和技术引入建筑工地&#xff0c;从施工现场源头抓起&#xff0c;最大程度地收集人员、安全、环境、材料等关键业务数据&#xff0c;依托物联网、互联网&#xff0c;建立云端大数据管理平台&#xff0c;形成“端云大数据”的业务体系和新的管理模式&a…

【CSS动画02--卡片旋转3D】

CSS动画02--卡片旋转3D 介绍代码HTMLCSS css动画02--旋转卡片3D 介绍 当鼠标移动到中间的卡片上会有随着中间的Y轴进行360的旋转&#xff0c;以下是几张图片的介绍&#xff0c;上面是鄙人自己录得一个供大家参考的小视频&#x1f92d; 代码 HTML <!DOCTYPE html>…

2023-08-20力扣今日二题

链接&#xff1a; 1312. 让字符串成为回文串的最少插入次数 题意&#xff1a; 如题 解&#xff1a; 动态规划&#xff0c;枚举回文串中点并递增回文串长度 初始状态若LR则单个字符为中点&#xff0c;需要添加0个字符成为回文串&#xff1b;若L1R则如果S[L]S[R]则需要添加…

BERT、ERNIE、Grover、XLNet、GPT、MASS、UniLM、ELECTRA、RoBERTa、T5、C4

BERT、ERNIE、Grover、XLNet、GPT、MASS、UniLM、ELECTRA、RoBERTa、T5、C4 ELMOBERTERNIE![在这里插入图片描述](https://img-blog.csdnimg.cn/274e31d0f8274c748d05abe2ec65fc73.png)GroverXLNetGPTMASSUniLMELECTRARoBERTaT5C4ELMO BERT

深入浅出Pytorch函数——torch.nn.init.uniform_

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 相关文章&#xff1a; 深入浅出Pytorch函数——torch.nn.init.calculate_gain 深入浅出Pytorch函数——torch.nn.init.uniform_ 深入浅出Pytorch函数——torch.nn.init.normal_ 深入浅出Pytorch函数——torch.nn.init.c…

数组

数组 一维数组二维数组 数组的特点&#xff1a; 放在一块连续的内存空间中数组中的每个元素都具有相同的数据类型 一维数组 一维数组的定义及初始化&#xff1a; int arr[3] {1, 2, 3}; // 定义了一个数组arr&#xff0c;包含1、2、3三个元素int arr[3]; // 定义了一个数…

chatGPT-对话爱因斯坦

引言 阿尔伯特爱因斯坦&#xff08; 1879年 3 月 14 日 – 1955 年 4 月 18 日&#xff09;是一位出生于德国的理论物理学家&#xff0c;被广泛认为成为有史以来最伟大、最有影响力的科学家之一。他以发展相对论而闻名&#xff0c;他还对量子力学做出了重要贡献&#xff0c;因…

rfc7234之http缓存

缓存概念 缓存处理请求步骤 缓存如果查询到某个请求已经有缓存&#xff0c;那么需要进一步检查该资源的新鲜度&#xff0c;根据新鲜度和请求中的字段综合评估是否要去服务端拉取新鲜的资源。 注意&#xff1a; 创建响应时候要注意版本匹配&#xff0c;如果服务器响应和客户端…