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。

题解:首先看到路径修改和子树查询,树链剖分就没得跑了,当然也可以写LCT

操作2/3用树剖自然好写,难的是一,换根怎么看怎么尬

想了一想,如果根就是询问点,子树就是整个区间

如果根在祖先,该点的子树不变.仍是按照正规的树剖查法查

如果根在询问点的任何一个子树中,那么该询问点的子树就变成了除了这个子树之外的所有区间.

主要是如何确定这个根在哪个子树中比较麻烦,写一个类似lca的玩意,倍增记录他的祖先,到时候一点点跳上去,复杂度还是可以接受的.

我一直以为是线段树写错了,果然做题太少了orz

代码如下:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson root<<1
#define rson root<<1|1
#define inf 0x3f3f3f3f
using namespace std; struct node
{
int lazy,m,l,r;
} tr[];
int n,deep[],son[],fa[],size[],id[],top[],c[],w[],cnt,rt;
vector<int> g[]; void push_up(int root)
{
tr[root].m=min(tr[lson].m,tr[rson].m);
} void push_down(int root)
{
tr[lson].m=tr[root].lazy;
tr[lson].lazy=tr[root].lazy;
tr[rson].m=tr[root].lazy;
tr[rson].lazy=tr[root].lazy;
tr[root].lazy=inf;
} void build(int root,int l,int r)
{
if(l==r)
{
tr[root].l=l;
tr[root].r=r;
tr[root].lazy=inf;
tr[root].m=w[l];
return ;
}
int mid=(l+r)>>;
tr[root].l=l;
tr[root].r=r;
tr[root].lazy=inf;
build(lson,l,mid);
build(rson,mid+,r);
push_up(root);
} void update(int root,int l,int r,int val)
{
if(l==tr[root].l&&r==tr[root].r)
{
tr[root].lazy=val;
tr[root].m=val;
return ;
}
int mid=(tr[root].l+tr[root].r)>>;
if(tr[root].lazy!=inf)
{
push_down(root);
}
if(l>mid)
{
update(rson,l,r,val);
}
else
{
if(r<=mid)
{
update(lson,l,r,val);
}
else
{
update(lson,l,mid,val);
update(rson,mid+,r,val);
}
}
push_up(root);
} int query(int root,int l,int r)
{
if(l>r)
{
return inf;
}
if(tr[root].l==l&&tr[root].r==r)
{
return tr[root].m;
}
int mid=(tr[root].l+tr[root].r)>>;
if(tr[root].lazy!=inf)
{
push_down(root);
}
if(l>mid)
{
return query(rson,l,r);
}
else
{
if(r<=mid)
{
return query(lson,l,r);
}
}
return min(query(lson,l,mid),query(rson,mid+,r));
} void dfs1(int now,int f,int dep)
{
deep[now]=dep;
fa[now]=f;
size[now]=;
int maxson=-;
for(int i=; i<g[now].size(); i++)
{
if(g[now][i]==f)
{
continue;
}
dfs1(g[now][i],now,dep+);
size[now]+=size[g[now][i]];
if(size[g[now][i]]>maxson)
{
son[now]=g[now][i];
maxson=size[g[now][i]];
}
}
} void dfs2(int now,int topf)
{
id[now]=++cnt;
w[cnt]=c[now];
top[now]=topf;
if(!son[now])
{
return ;
}
dfs2(son[now],topf);
for(int i=; i<g[now].size(); i++)
{
if(g[now][i]==fa[now]||g[now][i]==son[now])
{
continue;
}
dfs2(g[now][i],g[now][i]);
}
} void path_update(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
swap(x,y);
}
update(,id[top[x]],id[x],val);
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
swap(x,y);
}
update(,id[x],id[y],val);
} int sub_query(int x)
{
if(x==rt)
{
return query(,,cnt);
}
if(id[rt]<=id[x]+size[x]-&&id[rt]>=id[x])
{
return min(query(,,id[x]-),query(,id[x]+size[x],cnt));
}
return query(,id[x],id[x]+size[x]-);
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n-;i++)
{
int from,to;
scanf("%d%d",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
for(int i=;i<=n;i++)
{
scanf("%d",&c[i]);
}
scanf("%d",&rt);
dfs1(rt,,);
dfs2(rt,rt);
build(,,n);
int kd,ll,rr,vv;
for(int i=;i<=m;i++)
{
scanf("%d",&kd);
if(kd==)
{
scanf("%d",&vv);
rt=vv;
}
if(kd==)
{
scanf("%d%d%d",&ll,&rr,&vv);
path_update(ll,rr,vv);
}
if(kd==)
{
scanf("%d",&vv);
printf("%d\n",sub_query(vv));
}
}
}

最新文章

  1. 检索 COM 类工厂中 CLSID 为 {28E68F9A-8D75-11D1-8DC3-3C302A000000} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))
  2. python_day2
  3. 源码分析shiro认证授权流程
  4. weblogic开发模式与生产模式介绍
  5. windows下Socket链接溢出
  6. Java基础知识强化27:Object类之toString()方法
  7. UIBezierPath
  8. php新建数据库对象 基础知识
  9. android studio集成ijkplayer
  10. Android为什么使用Binder-android学习之旅(101)
  11. 【Python】爬虫
  12. mysql基本知识点梳理和查询优化
  13. 树莓派motion监控安装配置相关事情
  14. vue 去掉路由中的#
  15. HDU1007(最近点对)
  16. Django的基本开发环境配置和MTV模型
  17. 大学生Linux常用命令(一)
  18. jvm 性能调优 经验总结---转
  19. python开发_pickle
  20. JMeter 十一:参数化

热门文章

  1. 使用妹子UI开发的体验分享
  2. android签名生成和发布
  3. jenkins 离线安装插件 ,插件的下载地址
  4. 工具软件集合 Adobe AE PS Pr CC 2018 2019 破解教程
  5. 1009 Product of Polynomials
  6. float型数据与字节数组的转化
  7. sublime3环境配置
  8. Linux性能监测:磁盘IO篇
  9. Mysql实用知识点总结
  10. chkdsk工具怎么修复