一无聊就找树剖写

题意:一颗带点权的树,三种操作:1.换根 2.链赋值 3.查询子树最小值


如果没有换根的话直接就是裸的树剖了,对于换根的操作我们可以分类讨论。

1.如果查询的$x$就是根,那答案就是整棵树的最小值。

2.如果以1为根的dfs序中,根在$x$的子树之外,那很明显$x$的子树还是原来的子树。

3.如果以1为根的dfs序中,根在$x$的子树里面的话,画个图就能发现,找到$x$的孩子中作为根的父亲那个点,答案就是整棵树把整个点的子树去掉就行了。

其他地方跟树剖没什么区别…

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lint;
const int N=100005;
const lint INF=(1ll<<32);
inline lint read()
{
lint s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
return s*f;
}
struct edge
{
int to,nxt;
}edges[N<<1];
int n,m,cnt,rot,tot;
int head[N<<1],son[N],size[N],dep[N],top[N],dl[N],dr[N],rk[N],fa[N];
lint tr[N<<2],tag[N<<2],v[N]; #define lson (o<<1)
#define rson (o<<1|1)
inline void push_up(int o)
{
tr[o]=min(tr[lson],tr[rson]);
}
inline void push_down(int o)
{
if(tag[o]==-1)return;
tag[lson]=tag[rson]=tag[o];
tr[lson]=tr[rson]=tag[o];
tag[o]=-1;
}
inline void build(int o,int l,int r)
{
tag[o]=-1;
if(l==r)
{
tr[o]=v[rk[l]];
return;
}int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
push_up(o);
}
inline void modify(int o,int l,int r,int ql,int qr,lint val)
{
if(ql<=l&&r<=qr)
{
tag[o]=tr[o]=val;
return;
}push_down(o);
int mid=(l+r)>>1;
if(mid>=ql)modify(lson,l,mid,ql,qr,val);
if(mid+1<=qr)modify(rson,mid+1,r,ql,qr,val);
push_up(o);
}
inline lint query(int o,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return tr[o];
push_down(o);
int mid=(l+r)>>1;lint res=INF;
if(mid>=ql)res=min(res,query(lson,l,mid,ql,qr));
if(mid+1<=qr)res=min(res,query(rson,mid+1,r,ql,qr));
return res;
} #undef lson
#undef rson
inline void addEdge(int u,int v)
{
edges[++cnt]=(edge){v,head[u]};
head[u]=cnt;
}
#define cur edges[i].to
inline void dfs1(int x)
{
size[x]=1;
for(register int i=head[x];i;i=edges[i].nxt)
if(cur!=fa[x])
{
fa[cur]=x;dep[cur]=dep[x]+1;
dfs1(cur);size[x]+=size[cur];
if(size[son[x]]<size[cur])son[x]=cur;
}
}
inline void dfs2(int x,int t)
{
top[x]=t;dl[x]=++tot;rk[tot]=x;
if(son[x])dfs2(son[x],t);
for(register int i=head[x];i;i=edges[i].nxt)
if(cur!=fa[x]&&cur!=son[x])dfs2(cur,cur);
dr[x]=tot;
}
#undef cur
inline void modify_link(int a,int b,int val)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]])swap(a,b);
modify(1,1,n,dl[top[a]],dl[a],val);
a=fa[top[a]];
}
if(dep[a]>dep[b])swap(a,b);
modify(1,1,n,dl[a],dl[b],val);
}
inline lint query_tree(int x)
{
if(rot==x)return query(1,1,n,1,n);
if(dl[x]<=dl[rot]&&dl[rot]<=dr[x])
{
int y;
for(register int i=head[x];i;i=edges[i].nxt)
if(dl[edges[i].to]<=dl[rot]&&dl[rot]<=dr[edges[i].to])
{
y=edges[i].to;
break;
}
return min(query(1,1,n,1,dl[y]-1),query(1,1,n,dr[y]+1,n));
}else
{
return query(1,1,n,dl[x],dr[x]);
}
}
int main()
{
n=read();m=read();rot=1;
for(register int i=1;i<n;i++)
{
int u,v;u=read();v=read();
addEdge(u,v);addEdge(v,u);
}
for(register int i=1;i<=n;i++)v[i]=read();
rot=read();
dfs1(1);dfs2(1,1);build(1,1,n);
for(register int i=1;i<=m;i++)
{
int op,x,y,val;op=read();
if(op==1)
{
rot=read();
}else if(op==2)
{
x=read();y=read();val=read();
modify_link(x,y,val);
}else
{
x=read();
printf("%lld\n",query_tree(x));
}
}
}

[日常摸鱼]bzoj3083遥远的国度-树链剖分的更多相关文章

  1. BZOJ3083: 遥远的国度(树链剖分)

    题意 $n$个节点的树,每个点有权值,支持三种操作 1. 换根 2.把$x$到$y$路径上节点权值变为$z$ 3.询问路径最小值 Sol 啥?你说这是TopTree的裸题?那你写去啊 很显然,如果没有 ...

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

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

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

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

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

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

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

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

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

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

  7. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  8. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  9. luoguP3979 遥远的国度 树链剖分

    \(1, 2\)操作没什么好说的 对于\(3\)操作,分三种情况讨论下 \(id = rt\)的情况下,查整棵树的最小值即可 如果\(rt\)在\(1\)号点为根的情况下不在\(id\)的子树中,那么 ...

随机推荐

  1. ABBYY FineReader 15新增智能PDF文档转换功能

    ABBYY FineReader 15(Windows系统)新增智能PDF文档转换功能,可自动检测导入PDF数字文档的文本层质量,确保转变为可编辑格式后的准确结果:从表单字段和文本框中提取文本,准确保 ...

  2. 最全总结 | 聊聊 Python 办公自动化之 Word(下)

    1. 前言 关于 Word 文档的读写,前面两篇文章分别进行了一次全面的总结 最全总结 | 聊聊 Python 办公自动化之 Word(上) 最全总结 | 聊聊 Python 办公自动化之 Word( ...

  3. centos8 yum 升级nginx

    原文地址:https://blog.csdn.net/lpwmm/article/details/105627476 CentOS8的Yum仓库中内置的nginx版本是1.14.1,最近漏扫提示需要升 ...

  4. js 表格上checkbox 全选

    <table class="layui-table"> <thead> <tr> <th width="75"> ...

  5. workerman windows环境下无法启动问题

    问题描述 使用laravel框架composer加载workerman/gateway-worker扩展使用workerman做客服系统.通过laravel的command命令: php artisa ...

  6. Mockito 结合 Springboot 进行应用测试

    Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试:Spring Boot可以跟BDD(Behavier Driven ...

  7. LeetCode周赛#203 题解

    1561. 你可以获得的最大硬币数目 #贪心 题目链接 题意 有 3n 堆数目不一的硬币,你和你的朋友们打算按以下方式分硬币: 每一轮中,你将会选出 任意 3 堆硬币(不一定连续). Alice 将会 ...

  8. Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree 题解(贪心+易错)

    题目链接 题目大意 给你一课树,要你给每一条边分权值,每条边的权值大于0,他们的乘积等于k,而且要使得n-1条边1的数量尽可能少,定义 f(u,v)为u到v的边权和求 \(\max \sum_{i=1 ...

  9. sharding事务。

    我们这么操作: 本地事务,但是会发现如果有异常两边都回滚了.看代码如下: rollback看一看: cachedConnections中缓存了2个connection. 对于每个connection调 ...

  10. 如何将图片、html等格式转成pdf

    const int WWidth = 600; const int HHeight = 800; List<System.Drawing.Image> AllName = new List ...