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. Delphi Berlin 窗体代码分离风格 回到Delphi7传统风格

    回到Delphi7传统风格 Floating Form Designer You can now detach the form designer in both, VCL and FireMonke ...

  2. Socket IO Web实时推送

    1服务器pom.xml引入 <!-- 服务端 --> <dependency> <groupId>com.corundumstudio.socketio</g ...

  3. 进入一个docker容器

    Starting from Docker 1.3 you can use Docker exec to enter a Docker container : docker exec -it CONTA ...

  4. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  5. python字符串填充(转)

    ljust()方法返回字符串左对齐的字符串长度宽度.填充是通过使用指定的fillchar(默认为空格).如果宽度小于len(s)返回原始字符串.语法 以下是ljust()方法的语法: str.ljus ...

  6. python的map函数和reduce函数(转)

    map函数 map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例 ...

  7. 真验货客户尾缀sql

    '; --select * from TB_ADDBOMWG_LOG; --SELECT * FROM TB_MAN_ROUTING_QM; SELECT * FROM IN_ITEM WHERE I ...

  8. jquery 不选择第一个

    参考 https://zhidao.baidu.com/question/174343639.html th:not(':first')

  9. dreamwave基础

    WEBcs架构需要在客户段安装程序, 需要安装程序, 工作量会比较大, 需要安装和维护, 比如以后系统升级, 会很麻烦. 优点是一些业务逻辑可以在客户端, 可以减少服务器的一些压力, 客户端的界面操作 ...

  10. hdoj1014 互质

    Uniform Generator Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...