洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作。操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值。
解法:如果没有修改树根操作那么这题就是树链剖分的裸题。但是修改树根操作会使得题目变得复杂一些,这里直接说结论:我们先直接以1为根建树进行树链剖分,这样的话根固定了那么路径修改操作就照常,然后我们要考虑换根操作对查询的影响(这是重点)。
画图分析后可以发现,可以分为3种情况,①x==rt,询问的就是整棵树 ②x不在1到rt的路径上,对查询没有影响,查询照常 3 x在1到rt的路径上,这样会麻烦一些,仔细观察图发现其实查询就变成了查询除去(x的rt所在的子树)那么我们就可以先用倍增找到(x的rt所在的子树)这颗子树的根为 y=rt的dep[rt]-dep[x]-1级祖先。这样查询除去y的子树剩下的左右两个区间合并就是答案了。
这道题还是很不错的,做了能涨处理这样的换根问题的姿势。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=1LL<<;
const int N=1e5+;
int n,m,T,rt,num=,f[N][];
LL v[N];
struct node{
int dep,fa,sz,heavy;
int toseg,top; LL val;
}tree[N]; //原本的树
int totree[N<<]; //线段树点i代表原树的点totree[i] /*-------------------------以下为线段树-----------------------------*/
LL Min[N<<],tag[N<<];
void pushdown(int rt) {
if (!tag[rt]) return;
Min[rt<<]=tag[rt<<]=tag[rt];
Min[rt<<|]=tag[rt<<|]=tag[rt];
tag[rt]=;
}
void pushup(int rt) {
Min[rt]=min(Min[rt<<],Min[rt<<|]);
} void build(int rt,int l,int r) {
if (l==r) {
Min[rt]=tree[totree[l]].val; tag[rt]=;
return;
}
int mid=l+r>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushup(rt);
} void update(int rt,int l,int r,int ql,int qr,LL v) {
if (ql<=l && r<=qr) {
Min[rt]=tag[rt]=v;
return;
}
int mid=l+r>>;
pushdown(rt);
if (ql<=mid) update(rt<<,l,mid,ql,qr,v);
if (qr>mid) update(rt<<|,mid+,r,ql,qr,v);
pushup(rt);
} LL query(int rt,int l,int r,int ql,int qr) {
if (ql<=l && r<=qr) return Min[rt];
int mid=l+r>>; LL ret=INF;
pushdown(rt);
if (ql<=mid) ret=min(ret,query(rt<<,l,mid,ql,qr));
if (qr>mid) ret=min(ret,query(rt<<|,mid+,r,ql,qr));
return ret;
} /*--------------------------以下为树链剖分----------------------------*/
int cnt=,head[N<<],to[N<<],nxt[N<<];
void add_edge(int x,int y) {
nxt[++cnt]=head[x]; to[cnt]=y; head[x]=cnt;
} void dfs1(int x,int fa,int dep) { //点x的父亲为fa深度为dep
tree[x].dep=dep;
tree[x].fa=fa;
tree[x].sz=;
tree[x].val=v[x];
int maxson=-;
for (int i=head[x];i;i=nxt[i]) {
int y=to[i];
if (y==fa) continue;
f[y][]=x; //在dfs1的时候顺便求倍增数组
for (int j=;j<=T;j++)
f[y][j]=f[f[y][j-]][j-];
dfs1(y,x,dep+);
tree[x].sz+=tree[y].sz;
if (tree[y].sz>maxson) tree[x].heavy=y,maxson=tree[y].sz;
}
} void dfs2(int x,int top) { //点x所在树链的top
tree[x].toseg=++num;
tree[x].top=top;
totree[num]=x;
if (!tree[x].heavy) return; //叶子结点
dfs2(tree[x].heavy,top); //先剖分重儿子
for (int i=head[x];i;i=nxt[i]) { //再剖分轻儿子
int y=to[i];
if (y==tree[x].fa || y==tree[x].heavy) continue;
dfs2(y,y);
}
} void update2(int x,int y,LL z) { //修改x到y路径的值
while (tree[x].top!=tree[y].top) { //不在同一条链上
if (tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); //x为深度大的链
update(,,n,tree[tree[x].top].toseg,tree[x].toseg,z); //x向上跳的同时更新
x=tree[tree[x].top].fa; //深度大的向上跳
}
if (tree[x].dep>tree[y].dep) swap(x,y); //这里x和y在同一条链
update(,,n,tree[x].toseg,tree[y].toseg,z); //x和y这条链的更新
} int getfa(int x,int k) { //取得x的k级祖先
if (k<) return -;
for (int i=T;i>=;i--)
if (k>=(<<i)) x=f[x][i],k-=(<<i);
return x;
} int main()
{
cin>>n>>m;
T=(int)log2(n)+;
for (int i=;i<n;i++) {
int x,y; scanf("%d%d",&x,&y);
add_edge(x,y); add_edge(y,x);
}
for (int i=;i<=n;i++) scanf("%lld",&v[i]);
dfs1(,,);
dfs2(,);
build(,,n);
scanf("%d",&rt);
for (int i=;i<=m;i++) {
LL opt,x,y,z; scanf("%lld",&opt);
if (opt==) {
scanf("%d",&rt);
}
if (opt==) {
scanf("%lld%lld%lld",&x,&y,&z);
update2(x,y,z);
}
if (opt==) {
scanf("%lld",&x);
if (x==rt) printf("%lld\n",query(,,n,,n)); //x就是root
else if (x==getfa(rt,tree[rt].dep-tree[x].dep)) { //x在1到root的路径上
y=getfa(rt,tree[rt].dep-tree[x].dep-); //取得去掉部分的根(这要画图理解)
z=INF;
if (tree[y].toseg->=) z=min(z,query(,,n,,tree[y].toseg-));
if (tree[y].toseg+tree[y].sz<=n) z=min(z,query(,,n,tree[y].toseg+tree[y].sz,n));
printf("%lld\n",z);
} else { //其他情况,直接查询子树
printf("%lld\n",query(,,n,tree[x].toseg,tree[x].toseg+tree[x].sz-));
}
}
}
return ;
}
洛谷P3979 遥远的国度 树链剖分+分类讨论的更多相关文章
- 洛谷 P4114 Qtree1 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...
- [洛谷P3384] [模板] 树链剖分
题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...
- 洛谷.4114.Qtree1(树链剖分)
题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...
- 洛谷3384&bzoj1036树链剖分
值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
随机推荐
- 【转】优秀的Vue UI组件库
原文来源:https://www.leixuesong.com/3342 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司 ...
- Linux Centos 7 下部署 .NetCore + MySql + Redis + mssql2007 部署过程
1. net core 安装及运行配置 安装 1)rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-p ...
- 禁用usb是否一种方法?
CM_Request_Device_EjectW?? ddk sdk必须安装 https://blog.csdn.net/phmatthaus/article/details/49779585
- django 在保存数据前进行数据校验
我们想在保存用户进入数据库之前做一些字段的校验,先贴出代码: import re from django.db import models from django.db.models.signals ...
- Charles IOS https抓包
步骤 1.下载charles: https://www.charlesproxy.com/download/ 只有一个30天试用版,每次打开只能30分钟,如果想时间长点,就找破解版或者买个licenc ...
- laravel5.6 基于redis,使用消息队列(邮件推送)
邮件发送如何配置参考:https://www.cnblogs.com/clubs/p/10640682.html 用到的用户表: CREATE TABLE `recruit_users` ( `id` ...
- proxy-target-class="false"与proxy-target-class="true"区别
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11484063.html <aop:aspectj-autoproxy proxy-target- ...
- 怀旧浪潮来袭,小霸王游戏、windows95......曾经的经典哪些能戳中你的心怀?
随着前两天上架的 Rewound 在 iPhone 上复刻了 iPod Classic为大家掀起一场怀旧浪潮,那么除了 Rewound还有什么经典?今天我们就来怀旧一下那些曾经的经典.80经典小霸王游 ...
- Ubuntu备份与恢复
在使用Ubuntu之前,相信很多人都有过使用Windows系统的经历.如果你备份过Windows系统,那么你一定记忆犹新:首先需要找到一个备份工具(通常都是私有软件),然后重启电脑进入备份工具提供的软 ...
- java web项目的https配置
1.进入到jdk下的bin目录 keytool -v -genkey -alias tomcat -keyalg RSA -keystore d:/tomcat.keystore -validity ...