Codeforces 916E Jamie and Tree (换根讨论)
题目链接 Jamie and Tree
题意 给定一棵树,现在有下列操作:
$1$、把当前的根换成$v$;$2$、找到最小的同时包含$u$和$v$的子树,然后把这棵子树里面的所有点的值加$x$;
$3$、查询以$v$为根的子树的点权之和。
这道题其他都是常规操作,就是当前根结点为$cnt$的时候求$x$和$y$的$LCA$(操作$2$要用到)
我们假定解题的时候根一直不变(我一般都设$1$为根结点)
答案为$LCA(x,y)$ $xor$ $LCA(x, cnt)$ $xor$ $LCA(y, cnt)$
#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 lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 1e5 + 10;
const int ass = 4e5; vector <int> v[N]; int ti;
int tot;
int n, m;
int fp[N];
int deep[N], f[N], st[N], ed[N], father[N], sz[N], son[N];
int top[N];
int cnt; LL a[N];
LL sum[N << 2], lazy[N << 2]; void dfs1(int x, int fa, int dep){
deep[x] = dep;
father[x] = fa;
son[x] = 0;
sz[x] = 1;
st[x] = ++ti; for (auto u : v[x]){
if (u == fa) continue;
dfs1(u, x, dep + 1);
sz[x] += sz[u];
if (sz[son[x]] < sz[u]) son[x] = u;
}
ed[x] = ti;
} void dfs2(int x, int tp){
top[x] = tp;
f[x] = ++tot;
fp[f[x]] = x;
if (son[x]) dfs2(son[x], tp);
for (auto u : v[x]){
if (u == father[x] || u == son[x]) continue;
dfs2(u, u);
}
} 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 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];
} inline void pushup(int i){
sum[i] = sum[i << 1] + sum[i << 1 | 1];
} inline void pushdown(int i, int L, int R){
if (L == R) return;
int mid = (L + R) >> 1;
lazy[i << 1] += 1ll * lazy[i];
sum[i << 1] += 1ll * lazy[i] * (mid - L + 1);
lazy[i << 1 | 1] += 1ll * lazy[i];
sum[i << 1 | 1] += 1ll * lazy[i] * (R - mid);
lazy[i] = 0;
} void build(int i, int L, int R){
if (L == R){ sum[i] = 1ll * a[fp[L]]; return; }
int mid = (L + R) >> 1;
build(lson);
build(rson);
pushup(i);
} void update(int i, int L, int R, int l, int r, LL val){
if (l == L && R == r){
sum[i] += 1ll * val * (R - L + 1);
lazy[i] += 1ll * val;
return ;
} pushdown(i, L, R);
int mid = (L + R) >> 1;
if (r <= mid) update(lson, l, r, val);
else if (l > mid) update(rson, l, r, val);
else{
update(lson, l, mid, val);
update(rson, mid + 1, r, val);
} pushup(i);
} LL query(int i, int L, int R, int l, int r){
pushdown(i, L, R);
if (L == l && R == r) return sum[i];
int mid = (L + R) >> 1;
if (r <= mid) return query(lson, l, r);
else if (l > mid) return query(rson, l, r);
else return query(lson, l, mid) + query(rson, mid + 1, r);
} LL calc(int x){
return query(1, 1, n, f[x], f[x] + sz[x] - 1);
} LL work(int x, LL val){
update(1, 1, n, f[x], f[x] + sz[x] - 1, val);
} int calc_lca(int x, int y, int cnt){
return LCA(x, y) ^ LCA(x, cnt) ^ LCA(y, cnt);
} int main(){ scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%lld", a + i); ti = 0;
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, 0);
dfs2(1, 1); build(1, 1, n); cnt = 1; int ca = 0;
while (m--){
int op;
scanf("%d", &op); if (op == 3){
int x;
scanf("%d", &x);
if (x == cnt){
printf("%lld\n", calc(1));
continue;
} int lca = LCA(x, cnt);
if (lca == x){
int y = twz(x, cnt);
printf("%lld\n", calc(1) - calc(y));
continue;
} printf("%lld\n", calc(x));
} else if (op == 1){
int x;
scanf("%d", &x);
cnt = x;
} else{
int x, y;
LL val;
scanf("%d%d%lld", &x, &y, &val); int z = calc_lca(x, y, cnt);
if (z == cnt){
work(1, val);
continue;
} int lca = LCA(z, cnt);
if (lca == z){
int yy = twz(z, cnt);
work(1, val);
work(yy, -val);
continue;
} work(z, val);
}
} return 0;
}
Codeforces 916E Jamie and Tree (换根讨论)的更多相关文章
- CodeForces 916E Jamie and Tree(树链剖分+LCA)
To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...
- codeforces 916E Jamie and Tree dfs序列化+线段树+LCA
E. Jamie and Tree time limit per test 2.5 seconds memory limit per test 256 megabytes input standard ...
- BZOJ 3083 遥远的国度 (换根讨论 + 树链剖分)
题目链接 BZOJ3083 换根不能真正地换. 令当前的根为$cnt$,要查找的子树根为$x$ $1$.$x = cnt$,那么要查找的区域就是整棵树. $2$.$x$在以$cnt$为根的子树内,那 ...
- Jamie and Tree CodeForces - 916E (换根)
大意: n节点树, 每个点有权值, 三种操作: 1,换根. 2, lca(u,v)的子树权值全部增加x. 3, 查询子树权值和. 先不考虑换根, 考虑子树x加v的贡献 (1)对fa[x]到根的树链贡献 ...
- Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 sec ...
- Codeforces 1092 F Tree with Maximum Cost (换根 + dfs)
题意: 给你一棵无根树,每个节点有个权值$a_i$,指定一个点u,定义$\displaystyle value = \sum^v a_i*dist(u,v)$,求value的最大值 n,ai<= ...
- Codeforces 891D - Sloth(换根 dp)
Codeforces 题面传送门 & 洛谷题面传送门 换根 dp 好题. 为啥没人做/yiw 首先 \(n\) 为奇数时答案显然为 \(0\),证明显然.接下来我们着重探讨 \(n\) 是偶数 ...
- E. Tree Painting(树形换根dp)
http://codeforces.com/contest/1187/problem/E 分析:问得分最高,实际上就是问以哪个节点出发得到的分数最多,而呈现成代码形式就变成了换根,max其得分!!!而 ...
- Codeforces 997D - Cycles in product(换根 dp)
Codeforces 题面传送门 & 洛谷题面传送门 一种换根 dp 的做法. 首先碰到这类题目,我们很明显不能真的把图 \(G\) 建出来,因此我们需要观察一下图 \(G\) 有哪些性质.很 ...
随机推荐
- CF 497 div 2 B
B. Turn the Rectangles time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- Leetcode 567.字符串的排列
字符串的排列 给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列. 换句话说,第一个字符串的排列之一是第二个字符串的子串. 示例1: 输入: s1 = "ab&q ...
- Leetcode 542.01矩阵
01矩阵 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离. 两个相邻元素间的距离为 1 . 示例 1: 输入: 0 0 0 0 1 0 0 0 0 输出: 0 0 0 0 1 0 ...
- LeetCode with Python -> Linked List
21. Merge Two Sorted Lists Merge two sorted linked lists and return it as a new list. The new list s ...
- webform登陆界面样式丢失
本文摘抄自:http://blog.csdn.net/sssix/article/details/16945347 请阅读原文. Forms验证——登录界面样式实效? <authenticati ...
- 欧拉路&&欧拉回路 概念及其练习
欧拉路: 如果给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,这条路称为欧拉路: 如果给定无孤立结点图G,若存在一条回路,经过图中每边一次且仅一次,那么该回路称为欧拉回路. 存在欧拉回路的 ...
- linux文件备份到windows方法
目录 背景 方案 过程记录 在windows上创建共享目录 将windows上共享的目录绑定到/mnt目录下 问题处理 背景 需编写部门wiki备份数据脚本.但wiki部署在linux上,而需将备份数 ...
- import from 相对路径
项目目录 - server - static - src - - stroe - - router - - main.js - app.js src为前端文件,src目录下有main.js代码如下 i ...
- BZOJ2123 [Sdoi2013]森林 【主席树 + 启发式合并】
题目 输入格式 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...
- Codeforces Round #240 (Div. 2) B 好题
B. Mashmokh and Tokens time limit per test 1 second memory limit per test 256 megabytes input standa ...