洛谷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 ...
随机推荐
- WPF 基本图形
一.WPF的基本图形 WPF图形的基类是Shape,所有的wpf图形类都是继承于Shape.Height,Width等决定它所处的面积,位置等,在没有设置图形宽高的情况,坐标位置为所在的容器的坐标,设 ...
- Web 请求之--性能相关
本博客代码运行环境 python : Python 3.7.1rc1 version pip : pip 19.1.1 version Scrapy: scrapy 1.6.0 version asy ...
- Codeforces 1179D 树形DP 斜率优化
题意:给你一颗树,你可以在树上添加一条边,问添加一条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复. 思路:添加一条边之后,树变成了基环树.容易发现,以基环上的点为根的子树的点中的简单 ...
- IE历史纪录
signed int __cdecl sub_475790(_BYTE *a1) { signed int result; // eax DWORD v2; // [esp+10h] [ebp-10h ...
- java中wait()和sleep()的区别
前言 以前只知道一个结论,但是没法理解,现在水平上来了,自己代码中写了一个验证的方法. 1.先上结论:wait()会释放持有的锁,sleep()不会释放持有的锁 2.验证:看代码运行结果. packa ...
- JAVA读取Excel2003、2007、2010教程
import java.io.File;import java.io.FileInputStream;import org.apache.poi.ss.usermodel.Row;import org ...
- shell 提取文件的某行,并在行尾添加字符
sed -n '100,200p' file.txt #提取文件file.txt第100行到第200行的内容 sed 's/$/test/' file.txt #在行尾添加字符串test,$代表行尾
- noi2019感想
不知道怎么想的,我现在已经没有心情写一篇完整的游记了. 发挥的是真的太差,Day1该切的T2没有切掉,想的时候漏了一个性质,便由100->45. Day1的时间全花在了T3上,结果想歪了,最后只 ...
- SAS 读取数据文件
每次读取数据时需要告诉SAS3件事:1:数据存在哪里?2:数据的形式3:创建的数据集的类型(永久/临时) 1 读取SAS数据集 DATA temp; /*temp 为创建的数据集名称*/ INFILE ...
- spring+freemarker 乱码解决办法
这样应该可以了~ <!-- freemarker config --> <bean id="freemarkerConfig" class="org.s ...