3083: 遥远的国度

Time Limit: 10 Sec Memory Limit: 512 MB

Description

描述

zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

Input

第1行两个整数n m,代表城市个数和操作数。

第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。

第n+1行,有n个整数,代表所有点的初始防御值。

第n+2行一个整数 id,代表初始的首都为id。

第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

Output

对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

Sample Input

3 7

1 2

1 3

1 2 3

1

3 1

2 1 1 6

3 1

2 2 2 5

3 1

2 3 3 4

3 1

Sample Output

1

2

3

4

提示

对于20%的数据,n<=1000 m<=1000。

对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。

对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。

对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。

对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。

HINT

Source

zhonghaoxi提供

这题如果没有操作111就是一个裸的树链剖分:操作222路径修改,操作333维护子树最小值。

那么在加入了操作111之后,操作222的部分显然没有发生变化

代码:

inline void change(int x,int y,long long v){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,num[top[x]],num[x],v);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	update(1,num[y],num[x],v);
}

其中updateupdateupdate是指线段树的区间修改操作,numnumnum数组记录dfsdfsdfs序。

所以我们只需要考虑换根对维护子树最小值信息的影响,那么我们可以分类讨论一波:

我们设当前询问的子树的根为uuu,当前的根节点为rootrootroot。

第一种情况:lcalcalca(uuu,rootrootroot)!=uuu,那么我们发现在以rootrootroot为根时uuu原来的子树就是现在的子树,直接线段树区间查询。

第二种情况:uuu==rootrootroot,那么此时uuu就是根节点,直接返回线段树根节点的minminmin值

第三种情况:rootrootroot在uuu原来的子树内,即lcalcalca(rootrootroot,uuu)==uuu&&uuu!=rootrootroot,怎么做呢?

我们找到uuu在rootrootroot->uuu这条链上uuu的儿子sss,那么子树sss的补集就是我们查询的区间。

没有其他情况了

贴一发代码

#include<bits/stdc++.h>
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline long long read(){
	long long ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
	return ans;
}
struct Node{int l,r;long long minn,lz;}T[N<<2];
struct node{int v,next;}e[N<<1];
long long a[N];
int first[N],dep[N],top[N],fa[N],hson[N],siz[N],num[N],pred[N],root,n,m,cnt=0,tot=0;
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline void dfs1(int p){
	siz[p]=1,hson[p]=0;
	for(int i=first[p];i;i=e[i].next){
		int v=e[i].v;
		if(v==fa[p])continue;
		fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
inline void dfs2(int p,int tp){
	top[p]=tp,num[p]=++tot,pred[tot]=p;
	if(hson[p])dfs2(hson[p],tp);
	for(int i=first[p];i;i=e[i].next){
		int v=e[i].v;
		if(v!=fa[p]&&v!=hson[p])dfs2(v,v);
	}
}
inline long long min(long long a,long long b){return a<b?a:b;}
inline void pushup(int p){T[p].minn=min(T[lc].minn,T[rc].minn);}
inline void pushnow(int p,long long v){T[p].minn=v,T[p].lz=v;}
inline void pushdown(int p){
	if(T[p].lz==0)return;
	pushnow(lc,T[p].lz),pushnow(rc,T[p].lz),T[p].lz=0;
}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r,T[p].lz=0;
	if(l==r){T[p].minn=a[pred[l]];return;}
	build(lc,l,mid);
	build(rc,mid+1,r);
	pushup(p);
}
inline void update(int p,int ql,int qr,long long v){
	if(T[p].l>qr||T[p].r<ql)return;
	if(ql<=T[p].l&&T[p].r<=qr){pushnow(p,v);return;}
	pushdown(p);
	if(qr<=mid)update(lc,ql,qr,v);
	else if(ql>mid)update(rc,ql,qr,v);
	else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
	pushup(p);
}
inline long long query(int p,int ql,int qr){
	if(T[p].l>qr||T[p].r<ql)return 1e16;
	if(ql<=T[p].l&&T[p].r<=qr)return T[p].minn;
	pushdown(p);
	if(qr<=mid)return query(lc,ql,qr);
	if(ql>mid)return query(rc,ql,qr);
	return min(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline void change(int x,int y,long long v){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,num[top[x]],num[x],v);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	update(1,num[y],num[x],v);
}
inline int lca(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		x=fa[top[x]];
	}
	return dep[x]<dep[y]?x:y;
}
inline int fid(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		if(fa[top[x]]==y)return top[x];
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	return hson[y];
}
int main(){
	n=read(),m=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	for(int i=1;i<=n;++i)a[i]=read();
	root=read();
	dfs1(root);
	dfs2(root,root);
	build(1,1,n);
	while(m--){
		int op=read(),u=read();
		if(op==1){root=u;continue;}
		if(op==2){int v=read();long long w=read();change(u,v,w);continue;}
		if(u==root){printf("%lld\n",T[1].minn);continue;}
		int t=lca(u,root);
		if(t!=u){printf("%lld\n",query(1,num[u],num[u]+siz[u]-1));continue;}
		int s=fid(u,root);
		printf("%lld\n",min(query(1,1,num[s]-1),query(1,num[s]+siz[s],n)));
	}
	return 0;
}

2018.06.30 BZOJ3083: 遥远的国度(换根树剖)的更多相关文章

  1. 2018.10.30 NOIP训练 【模板】树链剖分(换根树剖)

    传送门 纯粹是为了熟悉板子. 然后发现自己手生了足足写了差不多25min而且输出的时候因为没开long longWA了三次还不知所云 代码

  2. 51nod1812树的双直径(换根树DP)

    传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考 ...

  3. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

  4. 2018.06.30 BZOJ 3932: [CQOI2015]任务查询系统(主席树)

    3932: [CQOI2015]任务查询系统 Time Limit: 20 Sec Memory Limit: 512 MB Description 最近实验室正在为其管理的超级计算机编制一套任务管理 ...

  5. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  6. 2018.06.30 cdq分治

    #cdq分治 ##一种奇妙的分治方法 优点:可以顶替复杂的高级数据结构:常数比较小. 缺点:必须离线操作. CDQ分治的基本思想十分简单.如下: 我们要解决一系列问题,包含修改和查询操作,我们将这些问 ...

  7. 2018.06.30 BZOJ4443: [Scoi2015]小凸玩矩阵(二分加二分图匹配)

    4443: [Scoi2015]小凸玩矩阵 Time Limit: 10 Sec Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N< ...

  8. 2018.06.30 BZOJ1857: [Scoi2010]传送带(三分套三分)

    1857: [Scoi2010]传送带 Time Limit: 1 Sec Memory Limit: 64 MB Description 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段 ...

  9. 2018.06.30 BZOJ1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MB Description windy定义了一种windy数.不含前导零且相邻两 ...

随机推荐

  1. leetcode551

    public class Solution { public bool CheckRecord(string s) { ; ; ; var preChar = '\0'; ; i < s.Len ...

  2. 8.tomcat认证访问

    转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 接上例:namespce的作用除了在前面提到的避免协同开发名字冲突外,还为认 ...

  3. Css 特性之 transition和transform

    CSS 有一些新的属性,可以简化代码的书写,用简单的代码就可以实现复杂的变化.不用像 js 那样,需要写很多代码 这里主要介绍三个属性:transition ,transform,以及translat ...

  4. Nginx打开目录浏览功能(autoindex)以及常见问题解决方案

    Nginx默认是不允许列出整个目录的.如需此功能,打开nginx.conf文件,在location server 或 http段中加入autoindex on;另外两个参数最好也加上去: autoin ...

  5. [图解tensorflow源码] 入门准备工作

     tensorflow使用了自动化构建工具bazel.脚本语言调用c或cpp的包裹工具swig.使用EIGEN作为矩阵处理工具.Nvidia-cuBLAS GPU加速计算库.结构化数据存储格式prot ...

  6. mysql允许远程登录

    Mysql为了安全性,在默认情况下用户只允许在本地登录,可是在有此情况下,还是需要使用用户进行远程连接,因此为了使其可以远程需要进行如下操作: 一.允许root用户在任何地方进行远程登录,并具有所有库 ...

  7. tensorflow生成随机数的操作 tf.random_normal & tf.random_uniform & tf.truncated_normal & tf.random_shuffle

    tf.random_normal 从正态分布输出随机值. random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name ...

  8. IDEA 码云 安装

    安装方式: 从IDEA插件仓库搜索Gitee下载并安装即可. 登陆并拉取项目代码 1. 启动 idea,选择Check out from Version Control-码云 2. 输入用户名和密码, ...

  9. 亲, 我们来再重申一遍"=="和"equals的区别

    今天经历的一个事情太丢脸了, 一个学弟向我请教问题, 是这样的: 一个字符串里面含有空格, 不允许使用.trim()和replace方法, 只用if和for将空格去掉, 题目很简单, 一开始我是这样写 ...

  10. 对象导航查询和OID查询(补)

    ----------------siwuxie095                                 对象导航查询         以客户和联系人为例(一对多)     1.应用场景 ...