题目大意:

  给定一棵有根树,每个点有一个权值,提供三种操作:

  1.将x节点变为根节点

  2.将x到y路径上的点的权值全部改为v

  3.询问x的子树中点权的最小值

思路:

  用DFS序剖分,记录每个节点入栈出栈的时间,其之间的区间即为子树。操作2用线段树直接搞,而换根先不管,可用原来的DFS序。询问时分类讨论:记最开始的根为root,换根之后,对于当前的根rtnow和询问子树U而言,

  ①rtnow==U,询问整棵树

  ②fa[rtnow]==U,询问除了rtnow所在子树以外的整棵树

  ③rtnow在U的子树里,且距离大于1,询问除了rtnow的除了其祖先是U的儿子的祖先的子树以外的整棵树

  ④rtnow不在U的子树里,询问U的子树

代码:

 #include<cstdio>
#include<iostream>
#define M 2000000
#define INF 2147483647
using namespace std; int cnt,dfn,n,m,a[M],to[M],hson[M],next[M],head[M],id[M],size[M],last[M],pos[M],pa[M],deep[M],top[M],cov[M<<],minv[M<<]; void ins(int x,int y)
{
to[++cnt]=y,next[cnt]=head[x],head[x]=cnt;
} void dfs1(int x)
{
size[x]=;
for (int i=head[x];i;i=next[i])
if (to[i]!=pa[x])
{
pa[to[i]]=x,deep[to[i]]=deep[x]+;
dfs1(to[i]),size[x]+=size[to[i]];
if (size[to[i]]>size[hson[x]]) hson[x]=to[i];
}
} void dfs2(int x,int tp)
{
id[x]=++dfn,pos[dfn]=x,top[x]=tp;
if (hson[x]) dfs2(hson[x],tp);
for (int i=head[x];i;i=next[i])
if (to[i]!=pa[x]&&to[i]!=hson[x]) dfs2(to[i],to[i]);
last[x]=dfn;
} void push_down(int k)
{
if (cov[k])
{
cov[k<<]=cov[k<<|]=minv[k<<]=minv[k<<|]=cov[k];
cov[k]=;
}
} void change(int cur,int L,int R,int l,int r,int val)
{
if (L==l && R==r) { cov[cur]=minv[cur]=val; return; }
int mid=L+R>>; push_down(cur);
if (r<=mid) change(cur<<,L,mid,l,r,val);
else if (l>mid) change(cur<<|,mid+,R,l,r,val);
else change(cur<<,L,mid,l,mid,val),change(cur<<|,mid+,R,mid+,r,val);
minv[cur]=min(minv[cur<<],minv[cur<<|]);
} int ask(int cur,int L,int R,int l,int r)
{
if (L==l && R==r) return minv[cur];
int mid=L+R>>; push_down(cur);
if (r<=mid) return ask(cur<<,L,mid,l,r);
if (l>mid) return ask(cur<<|,mid+,R,l,r);
return min(ask(cur<<,L,mid,l,mid),ask(cur<<|,mid+,R,mid+,r));
} void add(int x,int y,int val)
{
for (;top[x]!=top[y];x=pa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
change(,,n,id[top[x]],id[x],val);
}
if (deep[x]>deep[y]) swap(x,y);
change(,,n,id[x],id[y],val);
} int main()
{
scanf("%d%d",&n,&m);
int i,x,y,z,op,rt,root=;
for (i=;i<n;i++) scanf("%d%d",&x,&y),ins(x,y),ins(y,x);
for (i=;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&rt);dfs1(rt),dfs2(rt,rt);
for (i=;i<=n;i++) change(,,n,id[i],id[i],a[i]);
while (m--)
{
scanf("%d",&op);
if (op==) scanf("%d",&root);
if (op==) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
if (op==)
{
scanf("%d",&x);
if (x==root) printf("%d\n",ask(,,n,,n));
else if (pa[root]==x) printf("%d\n",min(ask(,,n,,id[root]-),last[root]==n?INF:ask(,,n,last[root]+,n)));
else if (id[root]>=id[x] && id[root]<=last[x])
{
y=root;
while (pa[top[y]]!=x && top[x]!=top[y]) y=pa[top[y]];
if (pa[top[y]]!=x) y=pos[id[x]+];
else y=top[y];
printf("%d\n",min(ask(,,n,,id[y]-),last[y]==n?INF:ask(,,n,last[y]+,n)));
}
else printf("%d\n",ask(,,n,id[x],last[x]));
}
}
return ;
}

bzoj3083 遥远的国度 题解的更多相关文章

  1. BZOJ3083 遥远的国度 【树链剖分】

    BZOJ3083 遥远的国度 Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcw ...

  2. [luogu3979][bzoj3083]遥远的国度

    [luogu传送门] [bzoj传送门] 题目描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcww ...

  3. BZOJ3083 遥远的国度 【树剖】

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

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

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

  5. 2018.06.30 BZOJ3083: 遥远的国度(换根树剖)

    3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 512 MB Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国 ...

  6. BZOJ3083 遥远的国度(树链剖分+线段树)

    考虑暴力树剖.那么修改路径和查询子树最小值非常简单. 对于换根当然不能真的给他转一下,我们只记录当前根是哪个.对于查询,如果查询点不在当前根到原根的路径上,显然换根是对答案没有影响的:如果是当前根,答 ...

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

    记最开始的根为root,换根之后,对于当前的根rtnow和询问子树U而言, ①rtnow==U,询问整棵树 ②fa[rtnow]==U,询问除了rtnow所在子树以外的整棵树 ③rtnow在U的子树里 ...

  8. BZOJ3083: 遥远的国度

    传送门 BZOJ100题辣(已经无法直视的正确率 树剖板子题,注意和dfs序结合,根据根的变化变换统计的方式即可. //BZOJ 3083 //by Cydiater //2016.10.23 #in ...

  9. BZOJ3083——遥远的国度

    1.题目大意:三个操作,换根,修改树上的某条路径,查询一个子树的最小值 2.分析:这个其实还是挺好做的,修改树上的某条路径,裸树剖,查询子树的最小值,这个是树剖满足dfs序 那么就是换根了,对吧,其实 ...

随机推荐

  1. Android Programming: Pushing the Limits -- Chapter 4: Android User Experience and Interface Design

    User Stories Android UI Design 附加资源 User Stories: @.通过写故事来设计应用. @.每个故事只关注一件事. @.不同的故事可能使用相同的组件,因此尽早地 ...

  2. tar 只解压tar包中某个文件

    sh-4.1# ls test.tar sh-4.1# tar -tf test.tar ./ecs20161207.png ./ecs.png ./ecs.xml ./rds.png ./Scree ...

  3. SQLServer系统监控

    http://blog.sina.com.cn/s/blog_519d269c0100gx09.html http://blog.csdn.net/qxlwuyuhui0801/article/det ...

  4. JS手机浏览器判断(转)

    整理查询一下,js判断手机浏览器的方法 <script type="text/javascript"> /* * 智能机浏览器版本信息:包括微信内置 * */ var ...

  5. poj 3278:Catch That Cow(简单一维广搜)

    Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 45648   Accepted: 14310 ...

  6. 信号量进程同步,王明学learn

    信号量进程同步 一组并发进程进行互相合作.互相等待,使得各进程按一定的顺序执行的过程称为进程间的同步. 信号量在进程同步时初始值为:0 信号量在进程互斥时初始值为:大于0的 本章节主要使用信号量,使的 ...

  7. ARM寄存器学习,王明学learn

    ARM寄存器学习 ARM微处理器共有37个32位寄存器,其中31个为通用寄存器,6个为状态寄存器.但是这些寄存器不能被同时访问,具体哪些寄存器是可以访问的,取决ARM处理器的工作状态及具体的运行模式. ...

  8. JNI数据类型(转)

    本文原创,转载请注明出处:http://blog.csdn.net/qinjuning 在Java存在两种数据类型: 基本类型 和 引用类型 ,大家都懂的 . 在JNI的世界里也存在类似的数据类型,与 ...

  9. 几种方式实现Javaweb页面跳转

    背景:       自己经手的一个java项目要实现带参页面跳转和页面跳转,完成任务后,总结一下自己知道了的几种方式. 实现: 首先我们有两大种方式来实现页面跳转:1.JS(javascript):2 ...

  10. Liferay 6.2 改造系列之二十四:修改liferay密码的加密方式

    为了便于后期与Cas集成过程中使用数据库用户的方便,将liferay密码的加密方式改为SHA. 在/portal-master/portal-impl/src/portal.properties配置文 ...