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:裸树剖+"换根" ...
随机推荐
- Alarm机制用于定时服务
获取一个 AlarmManager 的实例: AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE) ...
- JDK各版本新特性浅谈
JDK 5.0 自动拆装箱 枚举 可变参数 泛型 For -each 内省 静态导入 JDK 6.0 console开发控制台程序 轻量级HTTP ServerAPI 支持脚本语言 使用Compile ...
- luogu3375 【模板】KMP字符串匹配
nxt数组下标从1开始而a,b数组下标从0开始. #include <iostream> #include <cstring> #include <cstdio> ...
- flex布局之flex-grow和flex-shrink如何计算
此文已由作者张含会授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 关于盒模型布局 如何实现两栏布局? (表格) 流式, 浮动, 定位 如何选择? 流式 > 浮动 > ...
- Oracle 学习----:创建表(主键自增)
一.创建表 create table testTable ( Id numbere, name varchar2(100), age number, createTime date, primary ...
- java中使用二进制进行权限控制
基本概念 package test; publicclass Rights { publicstaticvoid main(String[] args) { int a=1; // 001 状态a i ...
- 【转】UGUI之用脚本动态的改变Button的背景图片 和 颜色
http://blog.csdn.net/u014771617/article/details/45102701 public Button button;void Start(){ColorBloc ...
- HTML5 新增绘图功能
<!DOCTYPE html> <html> <head lang="en"> <title></title> < ...
- BZOJ 3990: [SDOI2015]排序(搜索+剪枝)
[SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...
- 【神题】AtCoder 028 C Min Cost Cycle
TO BE DONE 思维题 十分巧妙的转化