洛谷 P3979 遥远的国度
修改某条路径上的值以及询问子树的最小值都最树剖的基础操作,那么如何实现换根呢?
考虑一下三种情况:
1.rot=询问的子树x,答案就是整棵树的最小值
2.rot在x的子树里,只有rot到x这一条链上的的节点的子树会变
找到x在rot方向上的子节点,答案就是除去这棵子树的最小值
3.rot不在x的子树里,那么rot是谁对x的子树没有影响,答案不变
那么就在询问时分类讨论一下就好了
#include<complex>
#include<cstdio>
using namespace std;
const int INF=<<;
const int N=1e5+;
struct node{
int v,nxt;
}e[N<<];
int n,m,s,Enum,tim,rot;
int val[N],front[N],fa[N][];
int fat[N],dep[N],tid[N],son[N],siz[N],top[N],rank[N];
int tree[N<<],lazy[N<<];
inline int qread()
{
int x=,j=;
char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')j=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*j;
}
inline void Insert(int u,int v)
{
e[++Enum].v=v;
e[Enum].nxt=front[u];
front[u]=Enum;
}
void dfs1(int x)
{
siz[x]=;
fa[x][]=fat[x];
for(int i=front[x];i;i=e[i].nxt)
{
int v=e[i].v;
if(v==fat[x])continue;
fat[v]=x;
dep[v]=dep[x]+;
dfs1(v);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]])
son[x]=v;
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
tid[x]=++tim;
rank[tid[x]]=x;
if(!son[x])return;
dfs2(son[x],tp);
for(int i=front[x];i;i=e[i].nxt)
{
int v=e[i].v;
if(v!=son[x] && v!=fat[x])
dfs2(v,v);
}
}
inline void PushUp(int rt)
{
tree[rt]=min(tree[rt<<],tree[rt<<|]);
}
inline void PushDown(int rt)
{
if(lazy[rt])
{
tree[rt<<]=tree[rt<<|]=lazy[rt];
lazy[rt<<]=lazy[rt<<|]=lazy[rt];
lazy[rt]=;
}
}
void Build(int l,int r,int rt)
{
if(l==r)
{
tree[rt]=val[rank[l]];
return;
}
int mid=l+r>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
PushUp(rt);
}
void Modify(int l,int r,int rt,int nowl,int nowr,int v)
{
if(nowl<=l && r<=nowr)
{
tree[rt]=lazy[rt]=v;
return;
}
PushDown(rt);
int mid=l+r>>;
if(nowl<=mid)Modify(l,mid,rt<<,nowl,nowr,v);
if(mid<nowr)Modify(mid+,r,rt<<|,nowl,nowr,v);
PushUp(rt);
}
int Query(int l,int r,int rt,int nowl,int nowr)
{
if(nowl<=l && r<=nowr)
return tree[rt];
PushDown(rt);
int mid=l+r>>,a=INF,b=INF;
if(nowl<=mid)a=Query(l,mid,rt<<,nowl,nowr);
if(mid<nowr)b=Query(mid+,r,rt<<|,nowl,nowr);
return min(a,b);
}
void FindFather()
{
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-];
}
inline int Lca(int a,int b)
{
if(dep[a]<dep[b])swap(a,b);
int tmp=dep[a]-dep[b];
for(int i=;i>=;i--)
if(tmp&(<<i))
a=fa[a][i];
if(a==b)return a;
for(int i=;i>=;i--)
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
return fa[a][];
}
inline void ModifyRoad(int x,int y,int v)
{
int f1=top[x],f2=top[y];
while(f1!=f2)
{
if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
Modify(,n,,tid[f1],tid[x],v);
x=fat[f1];f1=top[x];
}
if(dep[x]>dep[y])swap(x,y);
Modify(,n,,tid[x],tid[y],v);
}
inline int QueryTree(int x)
{
if(x==rot)return tree[];
int lca=Lca(x,rot);
if(lca==x)
{
int tmp=dep[rot]-dep[x]-,v=rot;
for(int i=;i<=;i++)
if(tmp&(<<i))
v=fa[v][i];
return min(Query(,n,,,tid[v]-),Query(,n,,tid[v]+siz[v],n));
}
return Query(,n,,tid[x],tid[x]+siz[x]-);
}
int main()
{
scanf("%d%d",&n,&m);
int u,v,p,x;
for(int i=;i<=n-;i++)
{
u=qread();v=qread();
Insert(u,v);
Insert(v,u);
}
for(int i=;i<=n;i++)
val[i]=qread();
dfs1();dfs2(,);
Build(,n,);
FindFather();
scanf("%d",&rot);
for(int i=;i<=m;i++)
{
p=qread();
if(p==)rot=qread();
if(p==)
{
u=qread();v=qread();x=qread();
ModifyRoad(u,v,x);
}
if(p==)
{
x=qread();
printf("%d\n",QueryTree(x));
}
}
return ;
}
洛谷 P3979 遥远的国度的更多相关文章
- [洛谷P3979]遥远的国度
题目大意:有一棵$n$个点的树,每个点有一个点权,有三种操作: $1\;x:$把根变成$x$ $2\;u\;v\;x:$把路径$u->v$上的点权改为$x$ $3\;x:$询问以$x$为根的子树 ...
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- 遥远的国度 (树链剖分换根),洛谷P3979
析:显然,若没有换根操作,则为树链剖分板子题,但是这道题我们考虑换根操作 考虑这样一个性质:在一棵树上,两点的距离路径是唯一的!! 也就是说,我们在修改路径上的点权时,不必考虑根在哪里,直接利用模板修 ...
- 洛谷P1514 [NOIP2010提高组T4]引水入城
P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP
题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...
- 洛谷P1710 地铁涨价
P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交 讨论 题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...
随机推荐
- [高清] Java从入门到精通第3版
------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...
- Linux进程间通信—使用共享内存
Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内 ...
- QTableWidget数据表格
void setRowHeight(int row, int height); //行高 void setVerticalHeaderLabels(const QStringList &lab ...
- js 数组 去重 算法(转载)
以下内容可能有重复部分,项目有用上,但还没来得急整理和验证. 一:https://www.cnblogs.com/jiayuexuan/p/7527055.html 1.遍历数组法 它是最简单的数组去 ...
- MySQL Backup--innobackupex操作日志
备份脚本: innobackupex \ --defaults-file="/export/servers/mysql/etc/my.cnf" \ --host="loc ...
- mybatis的XML中注释需谨慎
报错内容: java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2) ...
- c# MemoryStream 类
- python两则99乘法表
分别应用while和for的嵌套循环,适用于初学的人看看 x = 1 while x <= 9: y = 1 while y <= x: print (y,'*',x,'=',x*y,en ...
- [ipsec][strongswan] VirtualPN隧道网络加速FEC(forward error correction)
引用 跟一个网友就有关IPsec的网络加速以及降低延迟等问题进行了一些讨论,并总结了一写粗浅的看法. 因为FEC的资料并不多,所以分享出来,希望能被有需要的人看见:) 先说一下FEC. 我们使用ips ...
- Proxmox 命令使用方法
proxmox 虚拟机使用命令介绍 qm <command> <vmid> [OPTIONS] ...