树剖已经是人尽皆知的sb题了吗……

很早以前就想填掉这坑了……

考虑到树链唯一,进行操作并不会对换根产生影响,那么我们的换根操作只要记下root在哪里就好了

询问的时候分类讨论:

1:root == x 直接返回全树最大值就好了

2:lca(root, x) != x,那就和x没什么关系了,只要返回原子树最大值就好了

3:lca(root, x) ==  x,说明x在root的上方,那么找到x的儿子中root的祖先y,除了y的子树就都是x的子树了

跳树链和找lca可以用倍增实现

总复杂度 O(nlog2n)

Code(写的很长……):

#include <cstdio>
using namespace std; const int N = 1e5 + ;
const int Lg = ;
const int inf = << ; int n, qn, a[N], tot = , head[N], root;
int dfsc = , id[N], siz[N], top[N];
int w[N], dep[N], fa[N][Lg], son[N]; struct Edge {
int to, nxt;
} e[N << ]; inline void add(int from, int to) {
e[++tot].to = to;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ;
char ch = ;
int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int min(int x, int y) {
return x > y ? y : x;
} inline void chkMin(int &x, int y) {
if(y < x) x = y;
} inline void swap(int &x, int &y) {
int t = x;
x = y;
y = t;
} void dfs1(int x, int fat, int depth) {
siz[x] = , fa[x][] = fat, dep[x] = depth;
for(int i = ; i <= ; i++)
fa[x][i] = fa[fa[x][i - ]][i - ]; int maxson = -;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs1(y, x, depth + );
siz[x] += siz[y];
if(siz[y] > maxson)
maxson = siz[y], son[x] = y;
}
} void dfs2(int x, int topf) {
w[id[x] = ++dfsc] = a[x], top[x] = topf;
if(!son[x]) return;
dfs2(son[x], topf);
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa[x][] || y == son[x]) continue;
dfs2(y, y);
}
} inline int getLca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i];
if(x == y) return x;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][];
} namespace SegT {
int s[N << ], tag[N << ]; #define lc p << 1
#define rc p << 1 | 1
#define mid ((l + r) >> 1) inline void up(int p) {
if(p) s[p] = min(s[lc], s[rc]);
} inline void down(int p) {
if(tag[p] == inf) return;
s[lc] = tag[lc] = s[rc] = tag[rc] = tag[p];
tag[p] = inf;
} void build(int p, int l, int r) {
tag[p] = inf;
if(l == r) {
s[p] = w[l];
return;
} build(lc, l, mid);
build(rc, mid + , r);
up(p);
} void modify(int p, int l, int r, int x, int y, int v) {
if(x <= l && y >= r) {
s[p] = tag[p] = v;
return;
} down(p);
if(x <= mid) modify(lc, l, mid, x, y, v);
if(y > mid) modify(rc, mid + , r, x, y, v);
up(p);
} int query(int p, int l, int r, int x, int y) {
if(x <= l && y >= r) return s[p];
down(p); int res = inf;
if(x <= mid) chkMin(res, query(lc, l, mid, x, y));
if(y > mid) chkMin(res, query(rc, mid + , r, x, y));
return res;
} } using namespace SegT; inline void mtree(int x, int y, int v) {
for(; top[x] != top[y]; ) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
modify(, , n, id[top[x]], id[x], v);
x = fa[top[x]][];
}
if(dep[x] > dep[y]) swap(x, y);
modify(, , n, id[x], id[y], v);
} inline int ask(int x) {
if(root == x) return s[];
int y = getLca(x, root);
if(y == x) {
int z = root;
for(int i = ; i >= ; i--)
if(dep[fa[z][i]] > dep[y])
z = fa[z][i];
return min(query(, , n, , id[z] - ), query(, , n, id[z] + siz[z], n));
} else return query(, , n, id[x], id[x] + siz[x] - );
} int main() {
read(n), read(qn);
for(int x, y, i = ; i < n; i++) {
read(x), read(y);
add(x, y), add(y, x);
}
dfs1(, , ); for(int i = ; i <= n; i++) read(a[i]);
dfs2(, );
build(, , n); read(root);
for(int op; qn--; ) {
read(op);
if(op == ) read(root);
if(op == ) {
int x, y, v;
read(x), read(y), read(v);
mtree(x, y, v);
}
if(op == ) {
int x;
read(x);
printf("%d\n", ask(x));
}
} return ;
}

Luogu 3979 遥远的国度的更多相关文章

  1. 【luogu P3979 遥远的国度】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3979 除了换根操作都是裸的树剖 所以换根时考虑: 1.我查询的根等于换的根:无影响 2.我查询的根是换的根的 ...

  2. [Luogu] 遥远的国度

    https://www.luogu.org/problemnew/show/P3979 3种情况 x=root,很显然此时应当查询整棵树 lca(root,x)!=x ,此时直接查询x的子树即可,与换 ...

  3. 【Luogu】P3979遥远的国度(树链剖分)

    题目链接 不会换根从暑假开始就困扰我了……拖到现在…… 会了还是很激动的. 换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚…… 设全树的集合为G,以root为根,u在 ...

  4. 洛谷 3979 BZOJ 3083 遥远的国度

    [题解] 这道题除去根操作就是普通的树链剖分了.但是有换根操作怎么处理呢? 我们可以发现如果现在的根不在查询的点的子树里,那么对本次查询没有影响.如果现在的跟在查询的点x的子树里,那么答案将变为整棵树 ...

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

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

  6. Luogu 1514 引水入城 (搜索,动态规划)

    Luogu 1514 引水入城 (搜索,动态规划) Description 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,如上图 ...

  7. [luogu]P1514 引水入城[搜索][记忆化][DP]

    [luogu]P1514 引水入城 引水入城 题目描述在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形 ,如下图所示,其中每个格 ...

  8. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  9. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

随机推荐

  1. GCD多线程的使用

    转载自http://blog.csdn.net/nono_love_lilith/article/details/7829557 写得非常好 1.下面来看下如何使用gcd编程的异步 dispatch_ ...

  2. 安装Windows系统指南

    安装系统指南 WIN10PE内核与WIN8PE内核区别: Win10PE内核支持NVME(M.2)新硬盘,WIN8PE不支持NVME. 但是WIN8PE对老机器的适配更好一些,其他功能均一致. 多一个 ...

  3. NetCore博客

    NetCore外国一些高质量博客 https://www.cnblogs.com/fancunwei/p/9605627.html 前言 我之前看.netcore一些问题时候,用bing搜索工具搜到了 ...

  4. 高并发下Redis如何保持数据一致性(避免读后写)

    通常意义上我们说读后写是指针对同一个数据的先读后写,且写入的值依赖于读取的值. 关于这个定义要拆成两部分来看,一:同一个数据:二:写依赖于读.(记住这个拆分,后续会用到,记为定义一.定义二)只有当这两 ...

  5. Linux 命令行监视显卡使用情况

    本文由Suzzz原创,发布于 http://www.cnblogs.com/Suzzz/p/4106581.html ,转载请保留此声明. 在使用GPU做计算,比如跑 Deep Learning代码的 ...

  6. MySQL 用户权限详细汇总(转)

    1,MySQL权限体系 MySQL 的权限体系大致分为5个层级: 全局层级: 全局权限适用于一个给定服务器中的所有数据库.这些权限存储在mysql.user表中.GRANT ALL ON .和REVO ...

  7. 【Linux网络编程】基于TCP流 I/O多路转接(poll) 的高性能http服务器

    服务器比较简陋,为了学习poll的使用,只向客户端回写一条html语句.启动服务器后,浏览器发起请求,服务端向浏览器写回html,响应字符串,然后可以看到,浏览器解析并显示 Hello Poll!. ...

  8. SpringBoot自动化配置之四:SpringBoot 之Starter(自动配置)、Command-line runners

    Spring Boot Starter是在SpringBoot组件中被提出来的一种概念,stackoverflow上面已经有人概括了这个starter是什么东西,想看完整的回答戳这里 Starter ...

  9. javascript一些小的注意点

    try...catch 可以测试代码中的错误.try 部分包含需要运行的代码,而 catch 部分包含错误发生时运行的代码. 当try { 里面的代码 出现错误了 }catch(e){ 才执行下面的c ...

  10. DAY9-python并发之多进程理论

    一.背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...