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:裸树剖+"换根" ...
随机推荐
- C++从键盘读入数组并存储
C++从键盘读取任意长度的数组,现总结如下: //读取指定长度的数组 int main() { int n = 0; cin >> n; vector<int> p(n); f ...
- 1180: [CROATIAN2009]OTOCI(LCT)
1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 1200 Solved: 747[Submit][ ...
- RF、GBDT、XGBOOST常见面试算法整理
1. RF(随机森林)与GBDT之间的区别 相同点: 1)都是由多棵树组成的 2)最终的结果都是由多棵树一起决定 不同点: 1) 组成随机森林的树可以是分类树也可以是回归树,而GBDT只由回归树组 ...
- System.AccessViolationException”类型的第一次机会异常在 System.Data.dll 中发生 其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
管理员cmd中运行 netsh winsock reset
- Http请求连接池-HttpClient的AbstractConnPool源码分析
在做服务化拆分的时候,若不是性能要求特别高的场景,我们一般对外暴露Http服务.Spring里提供了一个模板类RestTemplate,通过配置RestTemplate,我们可以快速地访问外部的Htt ...
- [转]核函数K(kernel function)
1 核函数K(kernel function)定义 核函数K(kernel function)就是指K(x, y) = <f(x), f(y)>,其中x和y是n维的输入值,f(·) 是从n ...
- Python多进程之multiprocessing模块和进程池的实现
1.利用multiprocessing可以在主进程中创建子进程,提升效率,下面是multiprocessing创建进程的简单例子,和多线程的使用非常相似 ''' 代码是由主进程里面的主线程从上到下执行 ...
- Linux系统基础优化总结
请称呼我搬运工,哈哈 优化综合 https://www.cnblogs.com/yinshoucheng-golden/p/6149556.html (1)不用root管理,以普通用户的名义通过sud ...
- 习题:八数码难题(双向BFS)
八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...
- 【bzoj4066】简单题 KD-tree
题目描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数 ...