题意:给出一棵树,这棵树每个点有权值,然后有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 遥远的国度 树链剖分+分类讨论的更多相关文章

  1. 洛谷 P4114 Qtree1 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...

  2. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  3. 洛谷.4114.Qtree1(树链剖分)

    题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...

  4. 洛谷3384&bzoj1036树链剖分

    值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...

  5. BZOJ 3083 遥远的国度 树链剖分

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Descrip ...

  6. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  7. 【bzoj3083】遥远的国度 树链剖分+线段树

    题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...

  8. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  9. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

随机推荐

  1. GIT 的常见用法

    git init 新建代码库 git clone新建项目 git branch 查看分支 git config 显示配置 git config -e 显示配置文件 git config user.na ...

  2. C#编程--第二天

    一.变量:变量先声明,后赋值,再使用. 语法:变量类型 变量名=值: 变量类型: 分为基本数据类型和引用类 基本数据类型:整型.浮点型.字符型.布尔型 引用类:字符串.日期时间.枚举类型.结构类型 i ...

  3. 【记录】Mybatis-Generator 数据层代码生成器,自动生成dao类,mapper,pojo类

    Mybatis-Generator 工具来帮我们自动创建pojo类.mapper文件以及dao类并且会帮我们配置好它们的依赖关系. 官方文档地址:http://mybatis.org/generato ...

  4. ubuntu下安装chrome谷歌浏览器

    百度“chrome”然后登录谷歌浏览器官网下载deb包 cd到下载的目录下 sudo dpkg -i google-chrome*; 提示缺少依赖包,打入如下命令 sudo apt-get -f in ...

  5. String 字符串和StringBuffer的知识点总结

    String字符串 1  字符串.equals();                                                   equals和length的区别:equals ...

  6. Python向方法中传递自定义类型参数

    定义类型 class Fish: def __init__(self,x): self.num = xclass Turtle: def __init__(self,y): self.num = yc ...

  7. 静态部署TOMCAT

    常见部署方式:静态部署和容器化部署 一.下载tomcat安装包 下载地址:https://tomcat.apache.org/download-90.cgi 图上是显示最新版本,而我下载的是9.0.8 ...

  8. jsp获取url路径的方法

    如果你请求的URL是  http://localhost:8080/demo/Index.jsp request.getScheme() //输出:http request.getServerName ...

  9. 【leetcode】999. Available Captures for Rook

    题目如下: On an 8 x 8 chessboard, there is one white rook.  There also may be empty squares, white bisho ...

  10. mangodb数据库

    阅读目录 一 简介 二 MongoDB基础知识 三 安装 四 基本数据类型 五 CRUD操作 六 可视化工具 七 pymongo 一 简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1. ...