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\) 有哪些性质.很 ...
随机推荐
- V4L2学习(一)整体说明
1.概述 Video4Linux2是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口.凡是内核中的子系统都有抽象底层硬件的差异,为上层提供统一的接口和提取出公共代 ...
- nova boot添加volume_type参数支持
早前由于添加了全SSD的高性能Ceph集群,区别于现有的HDD集群,在OpenStack端需要能够选择使用两种集群.Cinder配置多Ceph后端的文档早已整理,整理文件夹时发现这篇为nova boo ...
- JVM——自定义类加载器
)以上两种情况在实际中的综合运用:比如你的应用需要通过网络来传输 Java 类的字节码,为了安全性,这些字节码经过了加密处理.这个时候你就需要自定义类加载器来从某个网络地址上读取加密后的字节代码,接着 ...
- SpringCloud 微服务一:spring boot 基础项目搭建
spring cloud是建立在spring boot的基础上的,而之前虽然听说过,也随便看了一下spring boot,却没有真正使用,因此还必须先花时间学一下spring boot. spring ...
- poj 3308 Paratroopers(二分图最小点权覆盖)
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8954 Accepted: 2702 Desc ...
- GBDT算法简述
提升决策树GBDT 梯度提升决策树算法是近年来被提及较多的一个算法,这主要得益于其算法的性能,以及该算法在各类数据挖掘以及机器学习比赛中的卓越表现,有很多人对GBDT算法进行了开源代码的开发,比较火的 ...
- 一次失败的刷题经历:[LeetCode]292之尼姆游戏(Nim Game)
最近闲来无事刷LeetCode,发现这道题的Accept Rate还是挺高的,尝试着做了一下,结果悲剧了,把过程写下来,希望能长点记性.该题的描述翻译成中文如下: 你正在和你的朋友玩尼姆游戏(Nim ...
- ogre3D学习基础1 -- 核心对象与脚本技术
一.核心对象介绍1.命名空间 Ogre3d使用了C++的特性--命名空间,可以防止命名混淆.使用方法也简单,using namespace Ogre;或者直接在使用时加上“Ogre::”的前缀,如Og ...
- MySQL一对一:一对多:多对多
学生表和课程表可以多对多 一个学生可以学多门课程 一门课程可以有多个学生: 多对多 *** 一个学生对应一个班级 一个班级对应多个学生: 一对多 *** 一个老师对应多个学生 多个学生对应一个老师:一 ...
- Kafka 配置参数
Broker Configs Property Default Description broker.id 每个broker都可以用一个唯一的非负整数id进行标识:这个id可以作为broker的 ...