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的操作,输出一行代表对应子树的最小点权值。

Solution

换根板子题。

先钦定1是根dfs树剖一波,然后考虑几个操作。

链修改的操作和树形没关系,直接做。

考虑查询操作,画图以后可以发现,当一个点\(u\)不在点\(v\)的子树中时(原树上),以点\(u\)为根时\(v\)的子树形态不变。证明可以考虑此时\(u\)一定是通过\(v\)的父亲和\(v\)连接的,换根后还是通过\(v\)的父亲,而其他的子树显然还在\(u\)下方。在此不做展开。

当点\(u\)在\(v\)的子树内时,发现\(u\)和\(v\)是通过指向\(u\)的儿子链接的。于是\(u\)的那个儿子儿子所能连接到的所有点(除通过\(v\)连接的以外)都会在新树上直接作为\(u\)的子树而不是\(v\)的子树,剩下的就是\(v\)的子树了。而那个儿子能链接的所有点恰好是该儿子的子树。于是查询时查询整棵树去掉该儿子子树的min即可。

另外特判\(v\)是根的情况。直接查询子树

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if(front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if(front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if(lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if(ch == '.') {
ch = IPT::GetChar();
double base = 1;
while((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if(lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if(x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while( x /= 10);
while(top) putchar(OPT::buf[top--]);
if(pt) putchar(aft);
} const int maxn = 100010;
const int maxm = 200010; struct Edge {
int to, nxt;
};
Edge edge[maxm]; int hd[maxn], ecnt=1;
inline void cont(ci from, ci to) {
Edge &e = edge[++ecnt];
e.to = to; e.nxt = hd[from]; hd[from] = ecnt;
} int n, m, vistime, newrot;
int sz[maxn], dfn[maxn], otn[maxn], son[maxn], top[maxn], rmp[maxn], MU[maxn], deepth[maxn], fa[maxn]; const int INF = (1ll << 31) - 1; struct Tree {
Tree *ls, *rs;
int v, tag, l, r; inline void pushup() {
this->v = INF;
if(this->ls) this->v = this->ls->v;
if(this->rs) this->v = std::min(this->rs->v, this->v);
} inline void maketag(ci _v) {
this->v = _v;
this->tag = _v;
} inline void pushdown() {
if(!this->tag) return;
if(this->ls) this->ls->maketag(this->tag);
if(this->rs) this->rs->maketag(this->tag);
this->tag = 0;
}
};
Tree *pool[maxm],qwq[maxm],*rot;
int poltp; void reading();
void dfs(ci, ci);
void DFS(ci, ci);
void buildpool();
void buildroot();
void build(Tree*, ci, ci);
void change(int, int, int);
void update(Tree*, ci, ci, ci);
int ask(Tree*, ci, ci); int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
reading();
qr(newrot) ;
dfs(newrot, 0); DFS(newrot, newrot);
buildpool(); buildroot();
build(rot, 1, n);
int a, b, c, d;
while (m--) {
a = 0; qr(a);
if (a == 1) {
newrot = 0; qr(newrot);
} else if (a == 2) {
b = c = d = 0; qr(b); qr(c); qr(d);
change(b, c, d);
} else if (a == 3) {
a=0; qr(a);
if (a == newrot) {
qw(rot->v, '\n', true);
} else if ((dfn[newrot] >= dfn[a]) && (dfn[newrot] <= otn[a])) {
int tp = newrot;
while(deepth[fa[top[tp]]] > deepth[a]) tp = fa[top[tp]];
if(dfn[top[tp]] > dfn[a]) tp = top[tp];
else tp = rmp[dfn[a] + 1];
qw(std::min(ask(rot, 1, dfn[tp] - 1), ask(rot, otn[tp]+1, n)), '\n', true);
} else {
qw(ask(rot,dfn[a],otn[a]), '\n', true);
}
}
}
return 0;
} void reading() {
int a,b;
for (rg int i = 1; i < n; ++i) {
a = b = 0; qr(a); qr(b);
cont(a, b); cont(b, a);
}
for(rg int i = 1; i <= n; ++i) qr(MU[i]);
} void dfs(ci u, ci pree) {
sz[u] = 1;
deepth[u] = deepth[fa[u] = edge[pree].to] + 1;
for (int i = hd[u]; i; i = edge[i].nxt) if (i != pree) {
int &to = edge[i].to;
dfs(to, i^1);
if(sz[to] > sz[son[u]]) son[u] = to;
}
} void DFS(ci u, ci tp) {
if((!u) || (dfn[u])) return;
dfn[u] = ++vistime;
rmp[vistime] = u;
top[u] = tp;
DFS(son[u], tp);
for (int i = hd[u]; i; i = edge[i].nxt) {
int &to = edge[i].to;
if(to == son[u]) continue;
DFS(to,to);
}
otn[u] = vistime;
} void buildpool() {
for (rg int i = 0; i < maxm; ++i) pool[i] = qwq+i;
poltp = maxm - 1;
} inline void buildroot() {
rot = pool[poltp--];
} void build(Tree *u, ci l, ci r) {
u->l = l; u->r = r;
if(l == r) {
u->v = MU[rmp[l]];
return;
}
int mid = (l + r) >> 1;
if(l <= mid) {
u->ls = pool[poltp--];
build(u->ls, l, mid);
}
if(mid < r) {
u->rs = pool[poltp--];
build(u->rs, mid+1, r);
}
u->pushup();
} void change(int u, int v, int p) {
while(top[u] != top[v]) {
if(deepth[top[u]] < deepth[top[v]]) std::swap(u, v);
update(rot, dfn[top[u]], dfn[u], p);
u = fa[top[u]];
}
if(deepth[u] < deepth[v]) std::swap(u, v);
update(rot, dfn[v], dfn[u], p);
} void update(Tree *u, ci l, ci r, ci v) {
if((u->l > r) || (u->r < l)) return;
if((u->l >= l) && (u->r <= r)) {u->maketag(v); return;}
u->pushdown();
if(u->ls) update(u->ls, l, r, v);
if(u->rs) update(u->rs, l, r, v);
u->pushup();
} int ask(Tree *u, ci l, ci r) {
if((u->l > r) || (u->r < l)) return INF;
if((u->l >= l) && (u->r <= r)) return u->v;
u->pushdown();
int _ret = INF;
if(u->ls) _ret = ask(u->ls, l, r);
if(u->rs) _ret = std::min(ask(u->rs, l, r), _ret);
return _ret;
}

Summary

树上的链操作与根无关

涉及到子树的操作可以通过讨论解决。

【树链剖分换根】P3979 遥远的国度的更多相关文章

  1. 遥远的国度 (树链剖分换根),洛谷P3979

    析:显然,若没有换根操作,则为树链剖分板子题,但是这道题我们考虑换根操作 考虑这样一个性质:在一棵树上,两点的距离路径是唯一的!! 也就是说,我们在修改路径上的点权时,不必考虑根在哪里,直接利用模板修 ...

  2. [模板] dfs序, 树链剖分, 换根

    树链剖分 树链剖分是一种对树的分治, 可以把树上的任意一条链分解为 \(O(\log n)\) 条在dfs序上相邻的子链, 便于数据结构(如线段树)来维护. 另外, 子树在dfs序上也是一个连续的区间 ...

  3. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  4. 7.18 NOI模拟赛 树论 线段树 树链剖分 树的直径的中心 SG函数 换根

    LINK:树论 不愧是我认识的出题人 出的题就是牛掰 == 他好像不认识我 考试的时候 只会写42 还有两个subtask写挂了 拿了37 确实两个subtask合起来只有5分的好成绩 父亲能转移到自 ...

  5. 树链剖分(附带LCA和换根)——基于dfs序的树上优化

    .... 有点懒: 需要先理解几个概念: 1. LCA 2. 线段树(熟练,要不代码能调一天) 3. 图论的基本知识(dfs序的性质) 这大概就好了: 定义: 1.重儿子:一个点所连点树size最大的 ...

  6. BZOJ 3083: 遥远的国度 dfs序,树链剖分,倍增

    今天再做一天树的题目,明天要开始专攻图论了.做图论十几天之后再把字符串搞搞,区域赛前再把计几看看. 3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 ...

  7. BZOJ_3083_遥远的国度_树链剖分+线段树

    BZOJ_3083_遥远的国度_树链剖分 Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神Ra ...

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

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

  9. BZOJ 3083 遥远的国度(树链剖分+LCA)

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

随机推荐

  1. 学习笔记之shell命令

    linux shell命令学习笔记:~这里只是对自己一些常用但是不熟悉的的命令进行记录 -------------------------------------------------------- ...

  2. 人脸检测及识别python实现系列(3)——为模型训练准备人脸数据

    人脸检测及识别python实现系列(3)——为模型训练准备人脸数据 机器学习最本质的地方就是基于海量数据统计的学习,说白了,机器学习其实就是在模拟人类儿童的学习行为.举一个简单的例子,成年人并没有主动 ...

  3. Redis 哨兵 Sentinel

    Redis Sentinel:redis集群应用,分布式系统.   多个Sentinal进程之间通过 gossip 协议来接收主服务器是否下线的信息,通过 Raft 一致性协议来决定故障转移及转移服务 ...

  4. JY播放器【蜻蜓FM电脑端,附带下载功能】

    今天给大家带来一款神器----JY播放器.可以不用打开网页就在电脑端听蜻蜓FM的节目,而且可以直接下载,对于我这种强迫症患者来说真的是神器.我是真的不喜欢电脑任务栏上面密密麻麻. 目前已经支持平台(蜻 ...

  5. C++11的左值引用与右值引用总结

    概念 在C++11中,区别表达式是左值或右值可以做这样的总结:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置).左值有持久的状态,而右值要 ...

  6. vs2017 asp.net FriendlyUrls 新特性

    这个包如何使用呢?其实很简单,只需将nuget包添加到项目中,再调用routes.EnableFriendlyUrls(),你就可以通过/Foo来访问/Foo.aspx了!你也能够利用URL片段将更多 ...

  7. Lucky Conversion(找规律)

    Description Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive int ...

  8. 冲刺ing-5

    第五次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 Leangoo的看板截图,燃尽图 蔺皓雯 编写博客 蔡晨旸 测试 曾茜 测试 鲁婧楠 测试 杨池宇 测试 成员遇到的问题 队员 问题 吴伟 ...

  9. ORACLE公司传奇历史

    ORACLE公司传奇 ORACLE公司之起源 很难想象,ORACLE 公司的这一段传奇居然要从 IBM 公司开始. 1970年的6月,IBM 公司的研究员埃德加·考特 (Edgar Frank Cod ...

  10. OpenLayers 3 入门教程

    OpenLayers 3 入门教程摘要OpenLayers 3对OpenLayers网络地图库进行了根本的重新设计.版本2虽然被广泛使用,但从JavaScript开发的早期发展阶段开始,已日益现实出它 ...