3083: 遥远的国度

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 4859  Solved: 1372
[Submit][Status][Discuss]

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提供

题解

我也是有B站账号的女人了!

这道题除了换根以外就很板子了,——所以我们聊聊换根。

首先在原根下建出一棵树,设当前的根为root。
对于子树k的操作:
1.root==k 那么对整棵树操作。
2.lca(root,k)!=k 也就是说root对k并没有什么影响,直接操作k。
3.lca(root,k)==k root在k的子树中,想象一下揪着一根毛拿起一顶假发......
那么对整个树中,除了原根意义下 k的儿子中含root的那一股 以外,的整棵树操作。
(也可以认为对整个树操作,然后对root那一股撤销操作

其实,所谓的换根操作,并不是要你每次把树再重新建一遍(复杂度起飞

而是考你分类讨论的能力QAQ

——

然后,一定一定要注意边界啊!字母不要混用啊!QAQ

以及 鉴于数据极接近maxint,不如直接longlong2333

 /**************************************************************
Problem: 3083
User: qwerta
Language: C++
Result: Accepted
Time:5528 ms
Memory:55532 kb
****************************************************************/ #include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define R register
const int MAXN=;
struct emm{
int e,f;
}b[*MAXN];
int h[MAXN];
int tot=;
void con(int u,int v)
{
b[++tot].f=h[u];
h[u]=tot;
b[tot].e=v;
b[++tot].f=h[v];
h[v]=tot;
b[tot].e=u;
return;
}
int d[MAXN],fa[MAXN],top[MAXN],siz[MAXN],z[MAXN];
void dfs(int x)
{
siz[x]=,top[x]=x;
int mac=,macc=-;
for(R int i=h[x];i;i=b[i].f)
if(!d[b[i].e])
{
d[b[i].e]=d[x]+;
fa[b[i].e]=x;
dfs(b[i].e);
siz[x]+=siz[b[i].e];
if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
}
z[x]=mac;
top[mac]=x;
return;
}
int q[MAXN],dfn[MAXN];
void dfss(int x)
{
q[++tot]=x;
dfn[x]=tot;
if(z[x])dfss(z[x]);
for(R int i=h[x];i;i=b[i].f)
if(d[b[i].e]==d[x]+&&b[i].e!=z[x])
dfss(b[i].e);
return;
}
int val[MAXN];
int fitop(int x)
{
if(top[x]==x)return x;
return top[x]=fitop(top[x]);
}
struct ahh{
int l,r,mid;
long long v,laz;
}a[*MAXN];
#define lz (i<<1)
#define rz ((i<<1)|1)
#define md a[i].mid
void build(int i,int ll,int rr)
{
a[i].l=ll;
a[i].r=rr;
if(ll==rr){a[i].v=val[q[ll]];return;}
md=(ll+rr)>>;
build(lz,ll,md);
build(rz,md+,rr);
a[i].v=min(a[lz].v,a[rz].v);
return;
}
int k;
void pushtag(int i)//啰嗦的pushtag
{
if(!a[i].laz)return;
a[i].v=a[i].laz;
if(a[i].l!=a[i].r)
{
a[lz].v=a[lz].laz=a[i].laz;
a[rz].v=a[rz].laz=a[i].laz;
}
a[i].laz=;
return;
}
void change(int i,int ll,int rr)
{
pushtag(i);//覆盖操作可不像累加有交换律啊!修改也要pushtagQAQ
if(a[i].l==ll&&a[i].r==rr){a[i].v=a[i].laz=k;return;}
if(rr<=md)change(lz,ll,rr);
else if(md+<=ll)change(rz,ll,rr);
else {change(lz,ll,md);change(rz,md+,rr);}
a[i].v=min(a[lz].v,a[rz].v);//记得一路更新上去QAQ
return;
}
long long ans;
void find(int i,int ll,int rr)
{
pushtag(i);
if(a[i].l==ll&&a[i].r==rr){ans=min(ans,a[i].v);return;}
if(rr<=md)find(lz,ll,rr);
else if(md+<=ll)find(rz,ll,rr);
else {find(lz,ll,md);find(rz,md+,rr);}
a[i].v=min(a[lz].v,a[rz].v);
return;
}
int filca(int u,int v)
{
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
return v;
}
int main()
{
//freopen("a.in","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
for(R int i=;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
con(u,v);
}
for(R int i=;i<=n;++i)
scanf("%d",&val[i]);
int s;
scanf("%d",&s);
d[s]=;
dfs(s);
tot=;
dfss(s);
for(R int i=;i<=n;++i)
top[i]=fitop(i);
build(,,n);
int rot=s;
for(R int ew=;ew<=m;++ew)//顺手打i->疯狂WA
{
int opt;
scanf("%d",&opt);
if(opt==)
{
int id;
scanf("%d",&id);
rot=id;
}
else if(opt==)
{
int u,v;
scanf("%d%d%d",&u,&v,&k);
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
change(,dfn[top[u]],dfn[u]);
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
change(,dfn[v],dfn[u]);
}
else
{
int x;
scanf("%d",&x);
ans=;
if(rot==x)
find(,dfn[s],dfn[s]+siz[s]-);
else
{
int lca=filca(rot,x);
if(lca!=x)
find(,dfn[x],dfn[x]+siz[x]-);
else
{
for(R int i=h[x];i;i=b[i].f)
if(d[b[i].e]==d[x]+)
{
if(dfn[b[i].e]<=dfn[rot]&&dfn[b[i].e]+siz[b[i].e]->=dfn[rot])
{
find(,,dfn[b[i].e]-);
if(dfn[b[i].e]+siz[b[i].e]<=n)//不注意边界->疯狂RE
find(,dfn[b[i].e]+siz[b[i].e],n);
}
}
}
}
printf("%lld\n",ans);
}
}
return ;
}

把AC率丢到地上蹂躏.jpg

最新文章

  1. 何为HDFS?
  2. SecureCRT在远程主机和本地之间传输文件
  3. Python Day 01
  4. UVa 488 - Triangle Wave
  5. php二维数组按照键值排序的方法
  6. 如何把TOMCAT 添加到服务中自动启动
  7. find 和 locate 命令
  8. 【BZOJ】【2693】JZPTAB
  9. Cacti优化之spine轮询器
  10. [转] Python list、tuple、dict区别
  11. linux函数的阻塞与非阻塞IO及错误处理
  12. Callable+Future+newFixedThreadPool的应用
  13. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用第三方组件
  14. 基于IIS的WCF
  15. 如何使用Linux的Crontab定时执行PHP脚本的方法[转载]
  16. Oralce 日期操作
  17. ubuntu更新提示/boot空间不足
  18. POJ3678 Katu Puzzle
  19. firewall-cmd --reload 防火墙
  20. 【BZOJ2770】YY的Treap 结论+线段树

热门文章

  1. Dance In Heap(一):浅析堆的申请释放及相应保护机制
  2. Irrlicht 3D Engine 笔记系列之 教程4 - Movement
  3. FFmpeg源码简单分析:结构体成员管理系统-AVOption
  4. 移植alsa-lib遇到的问题
  5. Spring学习【Spring概述】
  6. Audio原理图设计
  7. hdu4455 dp
  8. 浅析嵌入式C优化技巧
  9. matlab2016b -ubuntu 1604 -install- and -trouble -shooting--finally-all is ok!!
  10. 点击其它地方关闭DIV