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. neo4j 学习-2

    Neo4j 查询例句 MATCH (john {name: 'John'})-[:friend]->()-[:friend]->(fof) RETURN john.name, fof.na ...

  2. vcf格式简介

    1)背景 伴随着大规模的基因分型及测序工程的产生(例如1000 Genomes Project),之前的信息贮存格式例如gff文件它记录了每一个基因的详细信息,其中许多基因信息在基因组之间是共享的,而 ...

  3. InnoDB FULLTEXT

    1.概要 InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引.对于FULLTEXT索引的内容可以使用MATCH()…AGAIN ...

  4. print 不换行

    [print 不换行] 参考:http://zhidao.baidu.com/link?url=-qC2RyT5_GWzW_N-SyqJYgegVt2sSXwmMWGvHfk_4MjErhm_Pj23 ...

  5. WebDriverException:Element is not clickable at point - selenium执行过程中遇到的相关报错

    Element is not clickable at point (x, y) 这段可以忽略:本文来自 https://www.cnblogs.com/lozz/p/9947430.html 引起这 ...

  6. cubic与spline插值点处的区别

    cubic与spline都是Matlab的三次样条插值法,但是它们在插值点处仍然有着很微妙的区别,这个区别说明不了两种方法的好坏,只能根据实际情况进行合理筛选.以一维插值为例: clc clear % ...

  7. tf.FIFOQueue()

    Tensorflow–tf.FIFOQueue详解描述tf.FIFOQueue根据先进先出(FIFO)的原则创建一个队列.队列是Tensorflow的一种数据结构,每个队列的元素都是包含一个或多个张量 ...

  8. 操作符重载operator

    发现一篇好文: 转载: http://www.cnblogs.com/xiehongfeng100/p/4040858.html #include <iostream>#include & ...

  9. Oracle 数据库的绑定变量特性及应用

    Oracle 数据库的绑定变量特性及应用[-----]转载自https://www.cnblogs.com/rootq/(原地址) 关键词: 绑定变量(binding variable),共享池(sh ...

  10. vs2008 FileUpload 上传控件 Gridview传多个值

    拖fileupload控件,控件后加button1 lable1 lable2,还要在与本窗体同意目录下新建img文件夹protected void Button1_Click(object send ...