题目大意:有一棵$n$个点的树,每个点有一个点权,有三种操作:

  1. $1\;x:$把根变成$x$
  2. $2\;u\;v\;x:$把路径$u->v$上的点权改为$x$
  3. $3\;x:$询问以$x$为根的子树中最小的点权

题解:树剖,发现换根操作比较困难,可以进行一波分类讨论(下面的$lca$以及子树都是在以$1$为根的情况下(其实任意一个固定的点均可)

  1. $root=x:$就是询问整棵树
  2. $lca(root,x)\not=x:$就是正常询问$x$的子树
  3. $lca(root,x)=x:$就是整棵树减去$root$所在的子树

然后步骤三的减去$root$所在的子树中的找这棵子树可以用倍增来求

卡点:步骤三中只查询了$x$的子树减去$root$子树

C++ Code:

#include <algorithm>
#include <cstdio>
#include <cctype>
namespace std {
struct istream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
inline istream() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
fread(buf, 1, M, stdin);
}
inline istream& operator >> (int &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
#undef M
} cin;
struct ostream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
inline ostream& operator << (int x) {
if (!x) {
*++ch = '0';
return *this;
}
static int S[20], *top; top = S;
while (x) {
*++top = x % 10 ^ 48;
x /= 10;
}
for (; top != S; --top) *++ch = *top;
return *this;
}
inline ostream& operator << (const char x) {*++ch = x; return *this;}
inline ~ostream() {
#ifndef ONLINE_JUDGE
freopen("output.txt", "w", stdout);
#endif
fwrite(buf, 1, ch - buf + 1, stdout);
}
#undef M
} cout;
} #define maxn 100010
const int inf = 0x7fffffff; int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void addedge(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
} int n, m;
int w[maxn], W[maxn];
namespace SgT {
int V[maxn << 2], tg[maxn << 2];
inline void pushdown(int rt) {
int &__tg = tg[rt];
V[rt << 1] = tg[rt << 1] = V[rt << 1 | 1] = tg[rt << 1 | 1] = __tg;
__tg = 0;
} int L, R, num;
void build(int rt, int l, int r) {
if (l == r) {
V[rt] = W[l];
return ;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
V[rt] = std::min(V[rt << 1], V[rt << 1 | 1]);
}
void __modify(int rt, int l, int r) {
if (L <= l && R >= r) {
V[rt] = tg[rt] = num;
return ;
}
int mid = l + r >> 1;
if (tg[rt]) pushdown(rt);
if (L <= mid) __modify(rt << 1, l, mid);
if (R > mid) __modify(rt << 1 | 1, mid + 1, r);
V[rt] = std::min(V[rt << 1], V[rt << 1 | 1]);
}
void modify(int __L, int __R, int __num) {
L = __L, R = __R, num = __num;
__modify(1, 1, n);
} int ans;
void __query(int rt, int l, int r) {
if (L <= l && R >= r) {
ans = std::min(ans, V[rt]);
return ;
}
int mid = l + r >> 1;
if (tg[rt]) pushdown(rt);
if (L <= mid) __query(rt << 1, l, mid);
if (R > mid) __query(rt << 1 | 1, mid + 1, r);
}
int query(int __L, int __R) {
L = __L, R = __R;
ans = inf;
__query(1, 1, n);
return ans;
}
} int root;
int fa[maxn], sz[maxn], dfn[maxn], idx;
int son[maxn], top[maxn], dep[maxn]; namespace BZ {
#define M 17
int fa[maxn][M + 1];
inline void init(int u) {
*fa[u] = ::fa[u];
for (int i = 1; i <= M; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
}
inline int get_son(int x, int y) {
for (int i = M; ~i; i--) if (dep[fa[x][i]] > dep[y]) x = fa[x][i];
return x;
}
#undef M
}
using BZ::get_son; void dfs1(int u) {
BZ::init(u);
sz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
}
}
}
void dfs2(int u) {
dfn[u] = ++idx;
int v = son[u];
if (v) top[v] = top[u], dfs2(v);
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u] && v != son[u]) {
top[v] = v;
dfs2(v);
}
}
}
inline int LCA(int x, int y) {
if (x == y) return x;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
x = fa[top[x]];
}
return dep[x] > dep[y] ? y : x;
}
void modify(int x, int y, int z) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
SgT::modify(dfn[top[x]], dfn[x], z);
x = fa[top[x]];
}
if (dep[x] > dep[y]) std::swap(x, y);
SgT::modify(dfn[x], dfn[y], z);
}
inline int query(int x) {
if (root == x) return SgT::query(1, n);
if (LCA(x, root) != x) return SgT::query(dfn[x], dfn[x] + sz[x] - 1);
const int S = get_son(root, x), l = dfn[S], r = dfn[S] + sz[S] - 1;
int ans = inf;
if (1 < l) ans = SgT::query(1, l - 1);
if (r < n) ans = std::min(ans, SgT::query(r + 1, n));
return ans;
} int main() {
std::cin >> n >> m;
for (int i = 1, a, b; i < n; i++) {
std::cin >> a >> b;
addedge(a, b);
}
dfs1(1);
dfs2(top[1] = 1);
for (int i = 1; i <= n; i++) std::cin >> w[i];
for (int i = 1; i <= n; i++) W[dfn[i]] = w[i];
SgT::build(1, 1, n);
std::cin >> root;
while (m --> 0) {
int op, u, v, x;
std::cin >> op >> u;
switch (op) {
case 1:
root = u;
break;
case 2:
std::cin >> v >> x;
modify(u, v, x);
break;
case 3:
std::cout << query(u) << '\n';
}
}
return 0;
}

  

[洛谷P3979]遥远的国度的更多相关文章

  1. 洛谷 P3979 遥远的国度

    题目描述 修改某条路径上的值以及询问子树的最小值都最树剖的基础操作,那么如何实现换根呢? 考虑一下三种情况: 1.rot=询问的子树x,答案就是整棵树的最小值 2.rot在x的子树里,只有rot到x这 ...

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

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

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

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

  4. 洛谷P1514 [NOIP2010提高组T4]引水入城

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

  5. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  6. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  7. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  8. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  9. 洛谷P1710 地铁涨价

    P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交  讨论  题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...

随机推荐

  1. P1294 高手去散步

    P1294 高手去散步 题目背景 高手最近谈恋爱了.不过是单相思.“即使是单相思,也是完整的爱情”,高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开始 ...

  2. 机器学习常用算法(LDA,CNN,LR)原理简述

    1.LDA LDA是一种三层贝叶斯模型,三层分别为:文档层.主题层和词层.该模型基于如下假设:1)整个文档集合中存在k个互相独立的主题:2)每一个主题是词上的多项分布:3)每一个文档由k个主题随机混合 ...

  3. 「Python」conda与pip升级所有的包

    conda: conda update --a pip: pip freeze --local | grep -v '^-e' | cut -d = -f 1 | xargs -n1 sudo pip ...

  4. Python 更换国内pip源

    pip国内的一些镜像: 阿里云 http://mirrors.aliyun.com/pypi/simple/   中国科技大学 https://pypi.mirrors.ustc.edu.cn/sim ...

  5. MySQL☞自连接

    自连接:一张表中根据自身列之间的关联关系,自己跟自己链接. A.创建一个user表,且插入数据,数据如下: B.分析: 把user表看成两张表,一张员工表,一张领导表,发现员工表中lead(领导编号) ...

  6. Linux命令应用大词典-第17章 软件包管理

    17.1 rpm:RPM软件包管理器 17.2 rpmargs:处理RPM软件包 17.3 rpmbuild:构建RPM软件包 17.4 rpmdiff:比较两个软件包之间的不同 17.5 rpmel ...

  7. Codeforces-A. Shortest path of the king(简单bfs记录路径)

    A. Shortest path of the king time limit per test 1 second memory limit per test 64 megabytes input s ...

  8. adb 常用命令及操作

    获取序列号: adb get-serialno 查看连接计算机的设备: adb devices 重启机器: adb reboot 重启到bootloader,即刷机模式: adb reboot boo ...

  9. Python基础框架和工具

    最近在学Python金融大数据分析,在安装Python进行大数据分析的环境时遇到很多问题,例如:在安装pandas包时候就要到各种错误,总是缺少很多安装包,最后发现利用Python的Anaconda进 ...

  10. v-if或者v-repeat等不起作用

    v-if或者v-for等不起作用 在项目中,有时遇到了v-if或v-for等形式时,页面没起作用.以下可能是出现这些问题的原因: 1.绑定值是接口返回的某个属性值,而这个属性值不存在data()中,这 ...