BZOJ3083: 遥远的国度

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。

题解Here!
三种操作:换根,区间修改,子树最小值。
如果没有换根,这就是一道树剖的沙茶题。
但是有换根呢?
我们仍然以$1$为根建树。
然后我们分类讨论一下:
1. 如果$now==root$ ,那就是查询整棵树 ,直接输出$query\underline\ min(1,n)$就好了。
2. 如果$LCA(now,root)!=now$,这时根与$now$没有关系,直接查询$now$的子树即可。
3. 如果$LCA(now,root)==now$,这时比较麻烦。
我们可以先找一下$now$的所有儿子。
由于一个子树的$dfs$序是连续的。
所以,如果这个儿子的$id$小于等于$id[root]$,并且这个子树中的最大$dfs$序($id[son]+size[son]-1$)大于等于当前的$id[root]$。
那么就可以判断出$root$在这个儿子中或者就是这个儿子,记录下这个儿子。
还是那句话 :一个子树的$dfs$序是连续的。
这时$now$的子树就是去除包含$root$的那个儿子的子树的整棵树了。
当然,这题也可以用$LCT$维护子树信息做,只不过我不会啊。。。
附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) b[x].data
#define SIGN(x) b[x].c
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define WITDH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 100010
#define MAX (1LL<<62)
using namespace std;
int n,m,c=1,d=1,root;
int val[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],pos[MAXN],top[MAXN];
struct Tree{int next,to;
}a[MAXN<<1];
struct Segmeng_Tree{long long data,c;int l,r;
}b[MAXN<<2];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline void pushup(int rt){DATA(rt)=min(DATA(LSON),DATA(RSON));
}
inline void pushdown(int rt){if(SIGN(rt)==-1||LSIDE(rt)==RSIDE(rt))return;SIGN(LSON)=DATA(LSON)=SIGN(rt);SIGN(RSON)=DATA(RSON)=SIGN(rt);SIGN(rt)=-1;
}
void buildtree(int l,int r,int rt){LSIDE(rt)=l;RSIDE(rt)=r;SIGN(rt)=-1;if(l==r){DATA(rt)=val[pos[l]];return;}int mid=l+r>>1;buildtree(l,mid,LSON);buildtree(mid+1,r,RSON);pushup(rt);
}
void update(int l,int r,long long c,int rt){if(l<=LSIDE(rt)&&RSIDE(rt)<=r){SIGN(rt)=DATA(rt)=c;return;}pushdown(rt);int mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)update(l,r,c,LSON);if(mid<r)update(l,r,c,RSON);pushup(rt);
}
long long query(int l,int r,int rt){long long ans=MAX;if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);pushdown(rt);int mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)ans=min(ans,query(l,r,LSON));if(mid<r)ans=min(ans,query(l,r,RSON));return ans;
}
inline void add(int x,int y){a[c].to=y;a[c].next=head[x];head[x]=c++;a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){son[rt]=0;size[rt]=1;for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(!deep[will]){deep[will]=deep[rt]+1;fa[will]=rt;dfs1(will);size[rt]+=size[will];if(size[son[rt]]<size[will])son[rt]=will;}}
}
void dfs2(int rt,int f){id[rt]=d++;pos[id[rt]]=rt;top[rt]=f;if(son[rt])dfs2(son[rt],f);for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);}
}
int LCA(int x,int y){while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);return x;
}
void solve_update(int x,int y,int k){while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);update(id[top[x]],id[x],k,1);x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);update(id[x],id[y],k,1);
}
void solve_query(int x){if(x==root)printf("%lld\n",query(1,n,1));else{int lca=LCA(x,root);if(lca==x){int y;for(int i=head[x];i;i=a[i].next){int will=a[i].to;if(id[will]<=id[root]&&id[root]<=id[will]+size[will]-1){y=will;break;}}long long s=min(query(1,id[y]-1,1),query(id[y]+size[y],n,1));printf("%lld\n",s);}else printf("%lld\n",query(id[x],id[x]+size[x]-1,1));}
}
void work(){int f,x,y,k;while(m--){f=read();x=read();if(f==1){root=x;}else if(f==2){y=read();k=read();solve_update(x,y,k);}else solve_query(x);}
}
void init(){int x,y;n=read();m=read();for(int i=1;i<n;i++){x=read();y=read();add(x,y);}for(int i=1;i<=n;i++)val[i]=read();root=read();deep[1]=1;dfs1(1);dfs2(1,1);buildtree(1,n,1);
}
int main(){init();work();return 0;
}

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9471542.html

BZOJ3083: 遥远的国度相关推荐

  1. bzoj3083 遥远的国度 bzoj3626 LCA (树链剖分)

    今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...

  2. BZOJ3083: 遥远的国度(树链剖分)

    题意 $n$个节点的树,每个点有权值,支持三种操作 1. 换根 2.把$x$到$y$路径上节点权值变为$z$ 3.询问路径最小值 Sol 啥?你说这是TopTree的裸题?那你写去啊 很显然,如果没有 ...

  3. bzoj3083 遥远的国度

    树链剖分,先求出每个点的dfs序区间,查询时假设当前根为x,查询点为y,他们的dfs序分别为[xl,xr],[yl,yr],有三种情况,第一种x=y那么直接输出[1,n]的最小值,第二种这两个区间分离 ...

  4. 机器学习中决策树的随机森林_决策树和随机森林在机器学习中的使用

    机器学习中决策树的随机森林 机器学习 (Machine Learning) Machine learning is an application of artificial intelligence ...

  5. 【BZOJ3083】遥远的国度,树链剖分练习

    传送门 写在前面:链剖裸题里的战斗机 思路:Drusher向我推荐了这道污题,据说他请Claris调了一周才A,于是我怀着忐忑的心情开始看题,其他操作都好,一个换根把我搞懵逼了,"套spla ...

  6. P3979 遥远的国度

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

  7. 【LCT】遥远的国度(P3979)

    正题 P3979 题目大意 给你一棵树,让你进行一下操作: 把根节点修改为x 把x到y路径上的点权值修改为v 查询x子树中的最小权值 解题思路 可以用LCT维护该树 查询时先make_root(rt) ...

  8. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  9. [洛谷P3979]遥远的国度

    题目大意:有一棵$n$个点的树,每个点有一个点权,有三种操作: $1\;x:$把根变成$x$ $2\;u\;v\;x:$把路径$u->v$上的点权改为$x$ $3\;x:$询问以$x$为根的子树 ...

  10. 【BZOJ 3083】遥远的国度 树剖

    一开始看到有换根操作可是把我吓了一跳,我还以为要上top-tree呢,结果一开题解..........心塞 如果除去换根操作的话就是一道裸的树链剖分了,没什么难度,但是加上换根操作以后,别怕,其实联系 ...

最新文章

  1. 法总统:英国若“无协议脱欧” 将成最大输家
  2. DOS下获得当前文件夹目录的命令
  3. Summary of the Academic English Class
  4. 微信公众号页面支付接口java,[Java教程]微信公众号支付(三):页面调用微信支付JS并完成支付...
  5. linux笔记之常用的基本命令
  6. Android之Volley 源码解析
  7. python中什么最重要_Python 3中被忽视了的三大重要功能
  8. 美柚或赴境外IPO 阿里京东等为其客户
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的学习资源交互系统
  10. node文件服务器,nodejs一个简单的文件服务器的创建方法
  11. linux下activityMQ安装
  12. word上怎么把图片拼接到一起_图片合并,WORD如何将文字与图片合并
  13. yum安装freeswitch
  14. 1 一文详细阐述UI设计颜色搭配,受益匪浅~
  15. 卡尔曼滤波实例——预测橘子的轨迹
  16. 10行代码玩转弹性调度的小把戏
  17. 如何将Python打包后的exe还原成.py?
  18. openjudge666:放苹果
  19. ios html调起高德地图,iOS开发笔记 调起本地地图导航(百度、高德、腾讯、苹果自带)...
  20. 在openSUSE上编译aMule-DLP

热门文章

  1. C++ 关于“堆对象和栈对象”
  2. Code UI Automation脱离VS黑盒自动化测试工具编写
  3. fmt—fmt:formatDate的输出格式
  4. SqlServer中获取字符串中的数字部分
  5. 解决jQuery中dbclick事件触发两次click事件
  6. QA:mongoose中设置virtual后不工作问题
  7. mybatis-plus主键生成策略
  8. mysql自动多表联合更新_mysql多表联合更新 的 三种方法
  9. table添加一行且可编辑 vue_vue表格添加可编辑的一行后如何得到整个表格的数据...
  10. vs2019配置opencv_VS2019下Opencv配置