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\) 有哪些性质.很 ...
随机推荐
- The 2016 ACM-ICPC Asia Qingdao Regional Contest
A - Relic Discovery 签到 #include <cstdio> using namespace std; int T,n; long long ans=0; int ma ...
- 1250 Fibonacci数列(矩阵乘法快速幂)
1250 Fibonacci数列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 定义:f0=f1=1, f ...
- java高级编程技巧
1. boolean a= b==null;这句话很亮. public class Test { public static void main(String[] args) { String b=& ...
- git---gui使用
1.登陆的命令: git config –global user.email "1455971532@qq.com" git config –global user.name &q ...
- easyui-combogrid匹配查询
用到easyui-combogrid,数据比较少的情况,可以一页就显示完毕,然后直接下拉选择.但是对于数据量比较大的情况,一页显示全部显然不合适,好在从easyui-combogrid的数据加载方式可 ...
- linux学习(一) -- ubuntu下lamp环境的配置
以下为实测教程,希望能为大家提供帮助,转载请注明出处 ubuntu+apache+mysql+php7 第一.更换apt的源 1.复制原文件备份 sudo cp /etc/apt/source.lis ...
- 【Interleaving String】cpp
题目: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given: ...
- ogre3D学习基础17 --- 如何手动创建ogre程序
建立自己的Ogre程序 一直以来都是使用ExampleApplication.h来写程序,现在来看看它到底有什么神奇的地方. 首先,我们新建一个win32空项目 然后配置环境 最后新建define.c ...
- 最好用的远程连接工具TeamviWer13安装教程(Win10环境)
1.Teamviwer官网:https://www.teamviewer.com/zhCN/ 2.下载链接:https://dl.tvcdn.de/download/TeamViewer_Setup. ...
- LeetCode with Python -> Dynamic Programming
198. House Robber You are a professional robber planning to rob houses along a street. Each house ha ...