【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3083

【题目大意】

  链修改,子树最小值查询和换根操作

【题解】

  树链剖分练习题。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=100010,M=N<<2;
const int INF=~0U>>1;
int n,m,op,x,y,z,a[N],seq[N];
namespace Segment_Tree{
int tot;
struct node{int l,r,a,b;int tag,val;}T[M];
void build(int,int);
void Initialize(int n){
tot=0;
build(1,n);
}
void addtag(int x,int tag){
T[x].tag=tag;
T[x].val=tag;
}
void pb(int x){
if(T[x].tag!=0){
if(T[x].l){addtag(T[x].l,T[x].tag);addtag(T[x].r,T[x].tag);}
T[x].tag=0;
}
}
void up(int x){T[x].val=min(T[T[x].l].val,T[T[x].r].val);}
void build(int l,int r){
int x=++tot;
T[x].a=l;T[x].b=r;T[x].tag=T[x].l=T[x].r=0;
if(l==r){T[x].val=a[seq[l]];return;}
int mid=(l+r)>>1;
T[x].l=tot+1;build(l,mid);
T[x].r=tot+1;build(mid+1,r);
up(x);
}
void change(int x,int a,int b,int p){
if(T[x].a>=a&&T[x].b<=b){addtag(x,p);return;}
if(T[x].tag)pb(x);
int mid=(T[x].a+T[x].b)>>1;
if(mid>=a&&T[x].l)change(T[x].l,a,b,p);
if(mid<b&&T[x].r)change(T[x].r,a,b,p);
up(x);
}
int query(int x,int a,int b){
if(a>b)return INF;
if(T[x].a>=a&&T[x].b<=b)return T[x].val;
if(T[x].tag)pb(x);
int mid=(T[x].a+T[x].b)>>1; int res=INF;
if(mid>=a&&T[x].l)res=min(res,query(T[x].l,a,b));
if(mid<b&&T[x].r)res=min(res,query(T[x].r,a,b));
return res;
}
}
namespace Tree_Chain_Subdivision{
int ed,root,d[N],num[N],v[N<<1],vis[N],f[N],g[N<<1];
int nxt[N<<1],size[N],son[N],st[N],en[N],dfn,top[N];
void add_edge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
size[x]=1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
f[v[i]]=x,d[v[i]]=d[x]+1;
dfs(v[i]),size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
if(x==-1)return;
st[x]=++dfn;seq[dfn]=x;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
en[x]=dfn;
}
//查询x,y两点的lca
int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
return d[x]<d[y]?x:y;
}
//x是y的祖先,查询x到y方向的第一个点
int lca2(int x,int y){
int t;
while(top[x]!=top[y])t=top[y],y=f[top[y]];
return x==y?t:son[x];
}
//以root为根对x的子树操作
int subtree(int x,int n){
if(x==root){return Segment_Tree::query(1,1,n);}
if(st[x]>st[root]||en[x]<en[root]){return Segment_Tree::query(1,st[x],en[x]);}
int y=lca2(x,root);
return min(Segment_Tree::query(1,1,st[y]-1),Segment_Tree::query(1,en[y]+1,n));
}
//对x到y路径上的点进行操作
void chain(int x,int y,int p){
for(;top[x]!=top[y];x=f[top[x]]){
if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
Segment_Tree::change(1,st[top[x]],st[x],p);
}if(d[x]<d[y]){int z=x;x=y;y=z;}
Segment_Tree::change(1,st[y],st[x],p);
// 如果是边权转点权,则为change(st[y]+1,st[x])
}
void Initialize(){
memset(g,dfn=ed=0,sizeof(g));
memset(v,0,sizeof(v));
memset(nxt,0,sizeof(nxt));
memset(son,-1,sizeof(son));
}
}
int main(){
using namespace Tree_Chain_Subdivision;
scanf("%d%d",&n,&m);
Initialize();
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);add_edge(y,x);
}for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dfs(1);dfs2(1,1);
Segment_Tree::Initialize(dfn);
scanf("%d",&root);
while(m--){
scanf("%d",&op);
if(op==1)scanf("%d",&root);
if(op==2){scanf("%d%d%d",&x,&y,&z);chain(x,y,z);}
if(op==3){scanf("%d",&x);printf("%d\n",subtree(x,n));}
}return 0;
}

BZOJ 3083 遥远的国度(树链剖分+线段树)的更多相关文章

  1. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  2. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

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

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

  4. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  5. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  6. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

  7. BZOJ 3589 动态树 (树链剖分+线段树)

    前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...

  8. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  9. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  10. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

随机推荐

  1. LCD实验学习笔记(六):存储控制器

    s3c2440可使用地址空间为1GB(0x00000000到0x40000000). 1G空间分为8个BANK,每个BANK为128MB. 设27条地址线,和8个片选引脚(nGCS0-nGCS7). ...

  2. Perl6 Bailador框架(6):获取用户输入

    use v6; use Bailador; get '/' => sub { ' <html> <head><title></title>< ...

  3. python基础===python os.path模块

    os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回文件名 os.path.commonprefix(list) #返回list(多个路径) ...

  4. python基础===flask使用整理(转)

    flask 使用的一些整理 资源 Flask 文档|英文| expore flask| 快速教材| flask-admin| Flask-DebugToolbar| Flask-Login| Flas ...

  5. Redis 分片实现 Redis Shard [www]

    Redis 分片实现                                             Redis Shard https://www.oschina.net/p/redis-s ...

  6. Scrapy爬虫:抓取大量斗图网站最新表情图片

      一:目标 第一次使用Scrapy框架遇到很多坑,坚持去搜索,修改代码就可以解决问题.这次爬取的是一个斗图网站的最新表情图片www.doutula.com/photo/list,练习使用Scrapy ...

  7. ASPxTreeList的右键按钮事件

    ASPxTreeList应该是比较长用的控件了~现在就来说说它的右键按钮事件 这里实现的是右键里有折合和展开所有节点的功能 code: <dx:ASPxTreeList ID="ASP ...

  8. Mac 使用自带的Ruby 安装brew

    Homebrew简称brew,OSX上的软件包管理工具,在Mac终端可以通过brew安装.更新.卸载软件. 首先要安装brew,在 mac 中使用finder 搜索 终端(terminal)打开命令行 ...

  9. 其实linux下远程windows并不麻烦

    1:如果你是安装的ubuntu.那么安装完成之后就自带一个Remmina的远程桌面工具 2:这里我们需要安装rdesktop和tsclient,其中rdesktop是基于命令行的工具,tsclient ...

  10. 12:django 模板 内建过滤器

    django 模板 内建过滤器 add{{ value|add:"2" }} 对象的加法,如果都是整数类型,简单的算术加法:如果是列表,则是列表的相加 如果无法执行对象的相加,比如 ...