https://www.luogu.org/problemnew/show/P3979

3种情况

x=root,很显然此时应当查询整棵树

lca(root,x)!=x ,此时直接查询x的子树即可,与换根无关

lca(root,x)=x,此时我们应当查询与x相邻的节点中与root最近的点v在整棵树中的补集

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std; typedef long long ll;
typedef double dd;
const int maxn=;
const ll INF = (ll)1E14 + ; int h[maxn], n, m, top[maxn], lca[maxn][], son[maxn], edge, sz[maxn], dep[maxn];
int L[maxn], R[maxn], root, num, x, y, tx, ty, t, opt;
ll val, a[maxn]; struct Edge {
int to, ne;
} e[maxn * ]; struct Seg {
ll minn, same;
} seg[maxn << ]; void close() {
exit();
} void addedge(int x,int y) {
e[edge].to = y;
e[edge].ne = h[x];
h[x] = edge++;
} void dfs(int k,int from) {
sz[k] = ;
dep[k] = dep[from] + ;
son[k] = ;
for (int p=h[k]; p!=-; p=e[p].ne) {
int to = e[p].to;
if (to == from) continue;
lca[to][] = k;
for (int i=; i<=; i++)
lca[to][i] = lca[lca[to][i-]][i-];
dfs(to, k);
sz[k] += sz[to];
if (sz[to] > sz[son[k]]) son[k] = to;
}
} void build(int k,int from) {
L[k] = ++num;
top[k] = from;
if (son[k]) build(son[k], from);
for (int p=h[k]; p!=-; p=e[p].ne) {
int to = e[p].to;
if (to != lca[k][] && to != son[k])
build(to, to);
}
R[k] = num;
} int get_lca(int x,int y) {
if (dep[x] < dep[y]) swap(x, y);
int depth = dep[x] - dep[y];
for (int i=; i>=; i--)
if (depth & ( << i))
x = lca[x][i];
if (x == y) return x;
for (int i=; i>=; i--) {
if (lca[x][i] != lca[y][i]) {
x = lca[x][i];
y = lca[y][i];
}
}
return lca[x][];
} void pushup(int rt) {
seg[rt].minn = min(seg[rt<<].minn, seg[rt<<|].minn);
} void same(int rt,ll val) {
seg[rt].minn = val;
seg[rt].same = val;
} void pushdown(int rt) {
if (seg[rt].same) {
same(rt << , seg[rt].same);
same(rt << | , seg[rt].same);
seg[rt].same = ;
}
} void change(int L,int R,ll val,int l,int r,int rt) {
if (L <= l && r <= R) {
same(rt, val);
return;
}
int mid = (l + r) >> ;
pushdown(rt);
if (L <= mid)
change(L,R,val,lson);
if (mid + <= R)
change(L,R,val,rson);
pushup(rt);
} ll query(int L,int R,int l,int r,int rt) {
if (L > R) return INF;
if (L <= l && r <= R) {
return seg[rt].minn;
}
int mid = (l + r) >> ;
pushdown(rt);
ll ans = INF;
if (L <= mid)
ans = min(ans, query(L,R,lson));
if (mid + <= R)
ans = min(ans, query(L,R,rson));
pushup(rt);
return ans;
} void cc() {
tx = top[x];
ty = top[y];
while (tx != ty) {
if (dep[tx] < dep[ty]) {
swap(x, y);
swap(tx, ty);
}
change(L[tx], L[x], val, , n, );
x = lca[tx][];
tx = top[x];
}
if (dep[x] < dep[y])
swap(x, y);
change(L[y], L[x], val, , n, );
} void work() {
if (root == x) {
printf("%lld\n", seg[].minn);
return;
}
t = get_lca(root, x);
if (t != x) {
printf("%lld\n", query(L[x], R[x], , n, ));
return;
}
int depth = dep[root] - dep[x] - ;
int haha = root;
for (int i=; i>=; i--)
if (depth & ( << i))
haha = lca[haha][i];
printf("%lld\n", min(query(, L[haha] - , , n, ), query(R[haha] + , n, , n, )) );
} void init() {
scanf("%d %d",&n,&m);
memset(h, -, sizeof(h));
for (int i=; i<=n-; i++) {
scanf("%d %d",&x, &y);
addedge(x, y);
addedge(y, x);
}
for (int i=; i<=n; i++)
scanf("%lld",&a[i]);
dfs(, );
build(, );
for (int i=; i<=n; i++)
change(L[i], L[i], a[i], , n, );
scanf("%d",&root);
while (m--) {
scanf("%d",&opt);
if (opt == ) scanf("%d",&root);
if (opt == ) {
scanf("%d %d %lld",&x,&y,&val);
cc();
}
if (opt == ) {
scanf("%d",&x);
work();
}
}
} int main () {
init();
close();
return ;
}

最新文章

  1. ASP.NET、JAVA跨服务器远程上传文件(图片)的相关解决方案整合
  2. Fedora 23安装配置mysql数据库,修改初始密码及登陆
  3. 12个Linux进程管理命令介绍(转)
  4. java之内部类(InnerClass)----非静态内部类、静态内部类、局部内部类、匿名内部类
  5. 全程图解 手把手教您开启windows终端服务
  6. GridVeiw 使用
  7. 启用“关闭自动根证书更新”,解决Windows系统各种卡顿的问题(Visual studio 卡、远程桌面mstsc卡、SVN卡)
  8. HDU1013Digital Roots
  9. Android 高级UI设计笔记15:HorizontalScrollView之 实现画廊式图片浏览器
  10. 修改tomcat 启动45秒
  11. 省市县 三级 四级联动Javascript JQ 插件PCASClass.js
  12. iOS最新上线流程+续费 2015-7-20更新
  13. ECHO.js 纯javascript轻量级延迟加载
  14. CUDA开发时用到的各种Linux命令
  15. 【转载】HTTP Cookie学习笔记
  16. 编写OC高质量的代码的有效方法
  17. Unhandled event loop exception GC overhead limit exceeded
  18. HTML文档命名规则
  19. Xcode 断点无用,也不打印输出
  20. OSG模拟鼠标事件影响操纵器

热门文章

  1. 轻松搭建CAS 5.x系列(8)-在CAS Server增加双因素认证(DUO版)
  2. adminMongo:mongoDB node GUI(mongoDB图形化界面)
  3. 3、Concurrenthashmap实现原理(JDK版本1.7)
  4. DOM树节点关系
  5. 如何使 JavaScript 更高效?
  6. python自定义小工具:密码匿名化、毫秒时间显示、人类易读字节
  7. xshell生成公钥和私钥
  8. 【问题】No manual entry for pthread_create in section 3
  9. Thymeleaf整合到Spring Security,标签sec不起作用
  10. 机器学习 三剑客 之 pandas + numpy