BZOJ 3083 遥远的国度 (换根讨论 + 树链剖分)
题目链接 BZOJ3083
换根不能真正地换。
令当前的根为$cnt$,要查找的子树根为$x$
$1$、$x = cnt$,那么要查找的区域就是整棵树。
$2$、$x$在以$cnt$为根的子树内,那么要查找的区域就是以$x$为根的子树。
$3$、$x$在以$cnt$为根的子树外
(1)$x$不是$cnt$的祖先,那么要查找的区域就是以$x$为根的子树。
(2)$x$是$cnt$的祖先,设$y$为$x$到$cnt$方向上的第一个点,那么要查找的区域就是整棵树减去以$y$为根的子树。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define ls i << 1
#define rs i << 1 | 1
#define mid ((L + R) >> 1)
#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R const int N = 1e5 + 10; int f[N], fp[N], son[N], deep[N], father[N], sz[N], a[N], top[N];
int n, m, tot = 0;
int cnt;
int s[N << 2], lazy[N << 2];
vector <int> v[N]; void dfs1(int x, int fa, int dep){
deep[x] = dep;
father[x] = fa;
son[x] = 0;
sz[x] = 1;
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == fa) continue;
dfs1(u, x, dep + 1);
sz[x] += sz[u];
if (sz[son[x]] < sz[u]) son[x] = u;
}
} void dfs2(int x, int tp){
top[x] = tp;
f[x] = ++tot;
fp[f[x]] = x;
if (son[x]) dfs2(son[x], tp);
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == father[x] || u == son[x]) continue;
dfs2(u, u);
}
} inline void pushup(int i){ s[i] = min(s[ls], s[rs]); } inline void pushdown(int i){
if (lazy[i]){
s[ls] = lazy[ls] = lazy[i];
s[rs] = lazy[rs] = lazy[i];
lazy[i] = 0;
}
} void update(int i, int L, int R, int l, int r, int val){
if (l <= L && R <= r){
s[i] = lazy[i] = val;
return;
} pushdown(i);
if (l <= mid) update(lson, l, r, val);
if (r > mid) update(rson, l, r, val);
pushup(i);
} int query(int i, int L, int R, int l, int r){
if (l <= L && R <= r) return s[i]; pushdown(i);
int ret = INT_MAX;
if (l <= mid) ret = min(ret, query(lson, l, r));
if (r > mid) ret = min(ret, query(rson, l, r));
return ret;
} void modify(int x, int y, int val){
int f1 = top[x], f2 = top[y];
for (; f1 ^ f2; ){
if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
update(1, 1, n, f[f1], f[x], val);
x = father[f1], f1 = top[x];
} if (x == y){
update(1, 1, n, f[x], f[y], val);
return;
} if (deep[x] > deep[y]) swap(x, y);
update(1, 1, n, f[x], f[y], val);
return; } int twz(int x, int y){
int t;
for (; top[x] ^ top[y]; ) t = top[y], y = father[top[y]];
return x == y ? t : son[x];
} int LCA(int x, int y){
for (; top[x] ^ top[y]; ){
if (deep[top[x]] < deep[top[y]]) swap(x, y);
x = father[top[x]];
} return deep[x] > deep[y] ? y : x;
} int main(){ scanf("%d%d", &n, &m); rep(i, 0, 4e5 + 10) s[i] = INT_MAX; rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} dfs1(1, 0, 1);
dfs2(1, 1); rep(i, 1, n){
int x;
scanf("%d", &x);
update(1, 1, n, f[i], f[i], x);
} scanf("%d", &cnt); while (m--){
int op;
scanf("%d", &op);
if (op == 1) scanf("%d", &cnt);
else if (op == 2){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
modify(x, y, z);
} else{
int x;
scanf("%d", &x);
if (x == cnt){
printf("%d\n", query(1, 1, n, 1, n));
continue;
} int lca = LCA(x, cnt);
if (lca == x){
int y = twz(x, cnt);
int ret = INT_MAX;
int xx = f[y], yy = f[y] + sz[y] - 1;
if (xx >= 1) ret = min(ret, query(1, 1, n, 1, xx - 1));
if (yy < n) ret = min(ret, query(1, 1, n, yy + 1, n));
printf("%d\n", ret);
continue;
} printf("%d\n", query(1, 1, n, f[x], f[x] + sz[x] - 1));
}
} return 0;
}
BZOJ 3083 遥远的国度 (换根讨论 + 树链剖分)的更多相关文章
- Bzoj 4196: [Noi2015]软件包管理器 树链剖分
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 721 Solved: 419[Submit][Statu ...
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...
- BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)
题目链接 BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...
- BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )
首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- BZOJ - 3631 松鼠的新家 (树链剖分)
题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...
- BZOJ 4034 [HAOI2015]树上操作(树链剖分)
题目链接 BZOJ4034 这道题树链剖分其实就可以了. 单点更新没问题. 相当于更新 [f[x], f[x]]这个区间. f[x]表示树链剖分之后每个点的新的标号. 区间更新的话类似DFS序,求出 ...
- BZOJ 3631 松鼠的新家 - 树链剖分 / 树上差分
传送门 分析: 树链剖分:x->y,将x到y的路径加一,并将x端点的答案-1,最后统计答案. 树上差分:x->y,x+1,y+1,lca-1,fa[lca]-1,并将x打上标记,最后统计前 ...
- bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)
今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...
随机推荐
- HDU - 6514 Monitor(二维差分)
题意 给定一个\(n×m\)的矩阵.(\(n×m <= 1e7\)). \(p\)次操作,每次可以在这个矩阵中覆盖一个矩形. \(q\)次询问,每次问一个矩形区域中,是否所有的点都被覆盖. 解析 ...
- Codeforces Round #456 (Div. 2) A. Tricky Alchemy
传送门:http://codeforces.com/contest/912/problem/A A. Tricky Alchemy time limit per test1 second memory ...
- 同步锁之lock
一. synchronized的缺陷 当一个代码块被synchronized修饰时,同时该代码块被一个线程执行,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况: ...
- 测试环境docker化(一)—基于ndp部署模式的docker基础镜像制作
本文来自网易云社区 作者:孙婷婷 背景 我所在测试项目组目前的测试环境只有一套,在项目版本迭代过程中,开发或产品偶尔会在测试环境进行数据校验,QA人数在不断增加,各个人员在负责不同模块工作时也会产生脏 ...
- 数据库路由中间件MyCat - 使用篇(1)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 基本概念 直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍 业务场景:客户完成下单,快递员接受并更新运单 ...
- 【Linked List Cycle】cpp
题目: Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ...
- VC++中PostMessage、SendMessage和PeekMessage之间的区别
1, PostMessage只把消息放入队列,不管其他程序是否处理都返回,然后继续执行,这是个异步消息投放函数.而SendMessage必须等待其他程序处理消息完了之后才返回,继续执行,这是个同步消息 ...
- nyoj 题目17 单调递增最长子序列
单调递增最长子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4 输入 ...
- 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp
题目描述 对于一个给定长度为N的字符串,求它的第K小子串是什么. 输入 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置 ...
- 用 Ipe 画图
如何画一个箭头 首先要了解一个概念:「path object」. Path objects are objects that are formed with lines or curves, exam ...