P3979 遥远的国度 树剖
P3979 遥远的国度 树剖
需要想一下的树剖题,对于询问三需要处理换跟后的情况。我们以1为树根跑一遍剖分,对于换跟进行分类讨论,算出实际答案。讨论有三种情况:
(以1为树根的树上)
跟在询问节点的祖先上:因为不影响,所以直接求子树最小值
跟即询问节点:直接查全树
跟在询问节点子树中:画图容易得出,此时询问节点范围包含全树除了\(son\)的子树,其中\(son\)为跟向上跳达到询问节点的上一个节点。于是我们除去线段树区间\([idx[son], idx[son]+sz[son]-1]\)分左右区间讨论就好了。
#include <cstdio>
#include <algorithm>
#define MAXN 100010
#define ll long long
#define sl (x<<1)
#define sr (x<<1|1)
using namespace std;
int head[MAXN],vv[MAXN*2],nxt[MAXN*2],tot;
const int INF=0x3fffffff;
inline void add_edge(int u, int v){
vv[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int nod_val[MAXN];
int mxs[MAXN],sz[MAXN],dep[MAXN];
int f[MAXN][20];
void dfs1(int u, int fa){
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<=17;++i)
f[u][i]=f[f[u][i-1]][i-1];
sz[u]=1;
int mxsz=-1;
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
dfs1(v, u);
sz[u]+=sz[v];
if(mxsz<sz[v]){
mxsz=sz[v];
mxs[u]=v;
}
}
}
int idx[MAXN],topf[MAXN],cnt,wnew[MAXN];
void dfs2(int u, int top){
idx[u]=++cnt;
topf[u]=top;
wnew[cnt]=nod_val[u];
if(mxs[u]==0) return;
dfs2(mxs[u], top);
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==f[u][0]||v==mxs[u]) continue;
dfs2(v, v);
}
}
struct nod{
int l, r;
int val,lazy;
} tre[MAXN*4];
void buildt(int x, int l, int r){
tre[x].l=l,tre[x].r=r,tre[x].lazy=0;
if(l==r){
tre[x].val=wnew[l];
return;
}
int mid=(l+r)>>1;
buildt(sl, l, mid);
buildt(sr, mid+1, r);
tre[x].val=min(tre[sl].val, tre[sr].val);
}
void push_down(int x){
if(tre[x].lazy==0) return;
tre[sl].lazy=tre[sl].val=tre[x].lazy;
tre[sr].lazy=tre[sr].val=tre[x].lazy;
tre[x].lazy=0;
}
void change(int x, int l, int r, int val){
if(l<=tre[x].l&&tre[x].r<=r){
tre[x].lazy=tre[x].val=val;
return;
}
push_down(x);
int mid=(tre[x].l+tre[x].r)>>1;
if(l<=mid) change(sl, l, r, val);
if(mid<r) change(sr, l, r, val);
tre[x].val=min(tre[sl].val, tre[sr].val);
}
int query(int x, int l, int r){
if(l<=tre[x].l&&tre[x].r<=r){
return tre[x].val;
}
push_down(x);
int mid=(tre[x].l+tre[x].r)>>1;
int ans=INF;
if(l<=mid) ans=min(query(sl, l, r), ans);
if(mid<r) ans=min(query(sr, l, r), ans);
return ans;
}
void tre_change(int a, int b, int val){
while(topf[a]!=topf[b]){
if(dep[topf[a]]<dep[topf[b]]) swap(a,b);
change(1, idx[topf[a]], idx[a], val);
a=f[topf[a]][0];
}
if(dep[a]<dep[b]) swap(a,b);
change(1, idx[b], idx[a], val);
}
int tre_lca(int a, int b){
while(topf[a]!=topf[b]){
if(dep[topf[a]]<dep[topf[b]]) swap(a,b);
a=f[topf[a]][0];
}
if(dep[a]<dep[b]) return a;
return b;
}
int tre_query(int a){
return query(1, idx[a], idx[a]+sz[a]-1);
}
int get_son(int a, int b){
for(int i=17;i>=0;--i)
if(dep[f[b][i]]>dep[a]) b=f[b][i];
return b;
}
int n,q,cap;
int main()
{
scanf("%d %d", &n, &q);
for(int i=1;i<n;++i){
int a,b;
scanf("%d %d", &a, &b);
add_edge(a, b);
add_edge(b, a);
}
for(int i=1;i<=n;++i) scanf("%d", &nod_val[i]);
scanf("%d", &cap);
dfs1(1, 1);
dfs2(1, 1);
buildt(1, 1, n);
while(q--){
int opt;
scanf("%d", &opt);
if(opt==1){
scanf("%d", &cap);
}else if(opt==2){
int l,r,v;
scanf("%d %d %d", &l, &r, &v);
tre_change(l, r, v);
}else if(opt==3){
int t;
scanf("%d", &t);
int lca=tre_lca(t, cap);
if(t==cap) printf("%d\n", query(1, 1, n));
else if(lca!=t) printf("%d\n", tre_query(t));
else{
int son=get_son(t, cap);
int ans=min(query(1, 1, idx[son]-1), query(1, idx[son]+sz[son], n)); // 除去中间那个区间,分左右区间求
printf("%d\n", ans);
}
}else puts("Erro!");
}
return 0;
}
P3979 遥远的国度 树剖的更多相关文章
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- BZOJ 3083: 遥远的国度 (树剖+线段树)
传送门 解题思路 前两个操作都比较基础.对于第三个操作分类讨论一下,首先如果当前根不是要操作点的子树,那么就无影响,直接查询操作点的子树即可.第二种是当前根是操作点的子树,那就找到当前根到操作点这条链 ...
- 【树链剖分换根】P3979 遥远的国度
Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcw ...
- BZOJ3083 遥远的国度 【树剖】
题目 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务 ...
- 【Luogu】P3979遥远的国度(树链剖分)
题目链接 不会换根从暑假开始就困扰我了……拖到现在…… 会了还是很激动的. 换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚…… 设全树的集合为G,以root为根,u在 ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- 【luogu P3979 遥远的国度】 题解
题目链接:https://www.luogu.org/problemnew/show/P3979 除了换根操作都是裸的树剖 所以换根时考虑: 1.我查询的根等于换的根:无影响 2.我查询的根是换的根的 ...
- 【BZOJ3083/3306】遥远的国度/树 树链剖分+线段树
[BZOJ3083]遥远的国度 Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了 ...
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
随机推荐
- 1.ASP.NET Core Docker学习-Docker介绍与目录
Docker的优点: 1节约时间,快速部署和启动 2节约成本 3标准化应用发布 4方便做持续集成 5可以用Docker做为集群中的轻量主机或节点 6方便构建基于SOA或者微服务架构 的系统 学习目录: ...
- (六)在线文档编辑器的使用和数据字典(ueditor编辑器/my97datepicker日期控件)
使用ueditor编辑器注意: 1. 要把ueditor的jar包添加到WEB-INF/lib里. 2. 在做图片上传等功能时,必须重写struts的过滤器,否则图片流会被拦截程序无法得到图片. 3. ...
- ASP.NET WEB应用程序(.network4.5)MVC 程序的结构解读1
https://www.cnblogs.com/-beauTiFul/p/8036509.html 简介 开发环境:VS2015 ASP.NET:可以开发出几乎所有运行在Windows上的应用程序:. ...
- Unity UGUI Button 无法点击问题一例
理论上,只要一个按钮自己这一层或者子节点有一个控件勾选了RaycastTarget,并且按钮为Interactable的.并且不被其他可以点击的控件阻挡,那么这个按钮就可以被点击 在调一个界面时发现一 ...
- 三:后台的登录注册接口(moon项目,前面有一,二)
** 项目一共有 16 个页面,是一个电商网销项目,自己在网上的某网上找的一个要做的网站的设计图: 页面主要包括: 登录页 -- 注册页 -- 首页 -- 产品列表页 -- 产品详情页 -- 会员中 ...
- Vscode ftp
sftp的插件,作者是liximomo 安装插件: 在Vscode的商店中搜索sftp扩展 配置: 一般在开发项目时,总是有多个项目在同时开发.如果要为单一的项目配置的话,就需要打开此项目,快捷键ct ...
- leetcode-64. 最小路径和 · vector + DP
题面 Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right wh ...
- 升级xcode11&ios13的坑
Swift Packages 目前Pod跟SPM的兼容还没做好,配置好SPM后,Pod不能进行正常更新,先配置好Pod再集成SPM则没有问题 Pod以后的更新可能会解决这个问题,也会有越来越多的库支持 ...
- 【SQL server】SQL server基础(一)
一.关系型数据库 关系型数据库的基本元素是二维表,这些二维表可以被独立或者通过join语句连接起来使用.主键和外键是用来连接二维表之间的主要工具 1.主键(primary key)和外键(foreig ...
- Maven 三种archetype说明--转载
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 原文链接:https://blog.csdn.net/cx1110162/article/deta ...