题目链接  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. 菜鸟学Linux - Hard Link与Symbolic Link

    在学习Hard Link与Symbolic Link之前,需要大概了解一下inode与data block.在Linux的文件系统中,一个文件对应一个inode与若干个data block.inode ...

  2. OpenResty入门

    写一个小例子--输出随机字符串 编写nginx配置文件 location /random { content_by_lua_file /usr/local/openresty/nginx/conf/l ...

  3. easyui datagrid复选框控制单选

    使用easyui datagrid的时候,由于对数据表格操作太多,并且有单选和多选功能因此采用复选框.但是在单选的状态,使用CheckOnSelect和singleselect时发现,页面有明显延迟, ...

  4. CA证书申请、认证原理

    (一) 证书的申请 密钥文件的格式用OpenSSL生成的就只有PEM和DER两种格式,PEM的是将密钥用base64编码表示出来的,直接打开你能看到一串的英文字母,DER格式是二进制的密钥文件,直接打 ...

  5. cf984c Finite or not?

    一个十进制分数 \(p/q\) 在 \(b\) 进制下是有限小数的充要条件是 \(q\) 的所有质因子都是 \(b\) 的质因子. First, if \(p\) and \(q\) are not ...

  6. 一个iOS程序员眼中的跨域问题

    摘要: 跨域问题是web开发领域一个常见的问题,相信每个web开发者都遇到"跨域"的问题 最近公司的iOS开发任务比较少,所以自己最近开始了Web开发的任务,在用H5做了很多页面, ...

  7. sqlserver执行时间和自行效率

    SET STATISTICS PROFILE ON --SET STATISTICS IO ON --SET STATISTICS TIME ON declare @dtm datetime SQL语 ...

  8. Gym100623A Access Control Lists

    Gym 100623A Access Control Lists 这个题很sb啊,就是去设置个交换机 我们可以给一个IP进行设置,也可以对一个网段就行设置,但是IP是优于网段的,比如样例的第一个 网段 ...

  9. 在Myeclipse8.5中安装findbugs方法

    step 1:首先从官网下载findbugs插件:http://downloads.sourceforge.net/project/findbugs/findbugs%20eclipse%20plug ...

  10. 编译php 转

    LAOGAO added 20140907: configure: error: mcrypt.h not found. Please reinstall libmcrypt.复制代码 代码如下:wg ...