一无聊就找树剖写

题意:一颗带点权的树,三种操作: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. MathType如何输入微分上的点

    作为被老师们青睐的公式编辑器,MathType可以帮助插入各种数学符号和编辑数学公式,从而提高数学试卷的编写效率.但是作为新手,在编辑公式的时候难免有困难,比如就有人问:如何输入微分上的点?其实也是有 ...

  2. 如何在PDF文档上加水印

    当我们需要传输一些比较重要的文件时,往往会选择将文档转换为PDF文件,避免其他人复制.更改文档的内容. pdfFactory不仅可以为用户提供快速创建PDF的功能,同时还提供了添加水印的功能.有了水印 ...

  3. 使用Camtasia 让照片变身动态视频

    视觉化影像已经慢慢渗入我们平日的生活了,很多人已经慢慢地从单纯的文字记录,发展到使用照片记录生活,而视频化的记录也随着智能手机的普及而迅速发展起来.对于一些曾经使用照片记录的瞬间,我们也可以将其变身为 ...

  4. Vegas教程:教你制作热门人物消失特效

    在许多电影中,我们经常会看到一些人物逐渐消失的情景,这种情景一般都是通过后期技术处理的结果,现实生活中根本不可能出现,那么这种特效是如何制作处理的呢?下面小编就来教大家如何用Vegas    Pro ...

  5. python 如何跳过异常继续执行

    使用try...except...语句,类似于if...else...,可以跳过异常继续执行程序,这是Python的优势 用法如下: 1 2 3 4 5 6 try:            # 可能会 ...

  6. Leetcode1 - 10

    1. 两数之和 class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { ...

  7. NOIP2015 解题报告

    Day1 T3 运输计划 二分之后做一遍树上差分,找出被所有时间超限的运输计划覆盖的花费时间最长的航道,将其改造成虫洞. LCA 用倍增求可能会被卡常,建议用 Tarjan 求.

  8. C语言讲义——内联函数

    如果一些函数被频繁调用,不断地有函数入栈(Stack),会造成栈空间的大量消耗. 对应这种问题,可以使用内联函数(inline). 编译器会将内联函数的代码整段插入到调用的位置. #include & ...

  9. java Base64算法

    Base64算法并不是加密算法,他的出现是为了解决ASCII码在传输过程中可能出现乱码的问题.Base64是网络上最常见的用于传输8bit字节码的可读性编码算法之一.可读性编码算法不是为了保护数据的安 ...

  10. Java面试专题-基础篇(1)