题目链接  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 遥远的国度 (换根讨论 + 树链剖分)的更多相关文章

  1. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  2. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  3. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

  4. BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )

    首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...

  5. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  6. BZOJ - 3631 松鼠的新家 (树链剖分)

    题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...

  7. BZOJ 4034 [HAOI2015]树上操作(树链剖分)

    题目链接  BZOJ4034 这道题树链剖分其实就可以了. 单点更新没问题. 相当于更新 [f[x], f[x]]这个区间. f[x]表示树链剖分之后每个点的新的标号. 区间更新的话类似DFS序,求出 ...

  8. BZOJ 3631 松鼠的新家 - 树链剖分 / 树上差分

    传送门 分析: 树链剖分:x->y,将x到y的路径加一,并将x端点的答案-1,最后统计答案. 树上差分:x->y,x+1,y+1,lca-1,fa[lca]-1,并将x打上标记,最后统计前 ...

  9. bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)

    今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...

随机推荐

  1. 栈经典列题:Rails

    解题心得: 1.这题是先进后出的顺序,所以使用栈(先进后出表). 2.搞清楚题意,需要达成的序列和进入的序.不要弄混了. 3.思维混乱的时候要冷静,冷静,冷静~~~~! 题目: Description ...

  2. 笔记-网络-抓包-wireshark

    笔记-网络-抓包-wireshark 1.      开始 环境:win8笔记本,无线网 1.1.    无线网卡设置 因为需抓捕无线网卡上的数据包,需要进行一项设置,如捕获有线网卡,无需设置. 打开 ...

  3. poj 3308 Paratroopers(二分图最小点权覆盖)

    Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8954   Accepted: 2702 Desc ...

  4. phpstorm将本地代码传递到远程服务器

    由于对vim不太熟悉,效率比较低,作为过渡阶段,采用本地编写代码,然后上传到开发机上,进行调试 前提是服务器开启了ftp服务:http://www.cnblogs.com/redirect/p/693 ...

  5. mac攻略(八) -- 神器zsh和iterm2的配置

      1. 安装oh my zsh 安装命令: curl -L http://install.ohmyz.sh | sh 修改shell的方式: chsh -s /bin/zsh   2.安装cask( ...

  6. OpenStack之Glance源码简析

    Glance简介 OpenStack镜像服务器是一套虚拟机镜像发现.注册.检索. glance架构图: Glance源码结构: glance/api:主要负责接收响应镜像管理命令的Restful请求, ...

  7. 整理的一些Android开发类免费视频课程

    1.Android实战淘宝网项目视频:http://edu.ibeifeng.com/view-index-id-248.html 2.Android滚动视差实现课程:http://edu.ibeif ...

  8. 我爱学 Python 之文件

    读取文件 假设你已经在某个文件夹下创建了 "test.txt" 文件,且里面有一些内容,那你在当前位置输入 Python3,进入到交互模式,然后执行下面的操作: >>& ...

  9. 用最优方法从LinkedList列表中删除重复元素

    用运行速度最优的方法从LinkedList列表里删除重复的元素,例如A->B->BB->B->C,返回A->B->BB->C. 考试的时候没完全想明白,考完又 ...

  10. iOS自定义控件创建原理(持续更新)

    前言 因为如果要创建各种自定义控件根据需求的不同会有很多的差别,所以我就在这里,分析一些自定义控件的创建实现方法 弹出视图 1.把要弹出的视图装在一个控制器里面,自定义转场动画 2.创建一个弹出视图, ...