题面

题解

我们求它子树的权值和,一般用dfs序把树拍到线段树上做。

当它换根时,我们就直接把root赋值就行了,树的结构不去动它。

对于第二个操作,我们得到的链和根的相对位置有三种情况:

设两点为A、B,LCA 为 C,一个点x的dfs序为ld[x],从它的子树里出来时的dfs序为rd[x]

第一种情况,根是C的祖先,他的实际操作区间就是原本的子树区间[ld[C],rd[C]]

第二种情况,根在A、B路径上,那么它的实际LCA就应该是root,操作区间为[1,n]

第三种情况,根在C的子树上,A、B路径外,那么我们实际上要找到红色路径上最上方的点D

点D的父亲刚好在A、B路径上,那么实际子树就是除了D子树外的其他部分,操作区间为[1,ld[D])∪(rd[D],n]

把相应区间在线段树上区间加就行了。

3操作就相当于A=B的路径。

CODE

#include<cstdio>
#include<cstring>
#include<iostream>
//-----------F1
using namespace std;
#include<algorithm>
#include<cmath>
//-----------F2
#include<vector>
#include<stack>
#include<queue>
#include<map>
#define MAXN 100005
#define LL long long
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
//#pragma GCC optimize(2)
//#pragma G++ optimize(3)
//#define int LL
char char_read_before = 1;
inline int read() {
int f = 1,x = 0;char s = char_read_before;
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 - '0' + s;s = getchar();}
char_read_before = s;return x * f;
}
LL zxy = 1000000007ll; // 用来膜的
int n,m,i,j,s,o,k,root = 1;
LL a[MAXN],da[MAXN];
LL tre[MAXN<<2],lz[MAXN<<2],M;
inline void maketree(int n) {
M = 1; while(M < n+2) M <<= 1;
for(int i = 1;i <= n;i ++) {
tre[i + M] = da[i];
}
for(int i = M-1;i > 0;i --) {
tre[i] = tre[i<<1] + tre[i<<1|1];
}
}
inline void addtree(int l,int r,LL y) {
if(l > r) return ;
// printf("add %lld to [%d,%d]\n",y,l,r);
int s = M + l - 1,t = M + r + 1;
int ls = 0,rs = 0,sz = 1;
while(s || t) {
tre[s] += ls * y;
tre[t] += rs * y;
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) tre[s^1] += y * sz,lz[s^1] += y,ls += sz;
if(t & 1) tre[t^1] += y * sz,lz[t^1] += y,rs += sz;
}
s >>= 1; t >>= 1; sz <<= 1;
}
return ;
}
inline LL findtree(int l,int r) {
if(l > r) return 0;
int s = M + l - 1,t = M + r + 1;
int ls = 0,rs = 0,sz = 1;
LL ans = 0;
while(s || t) {
ans += ls * lz[s];
ans += rs * lz[t];
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) ans += tre[s^1],ls += sz;
if(t & 1) ans += tre[t^1],rs += sz;
}
s >>= 1; t >>= 1; sz <<= 1;
}
return ans;
}
vector<int> g[MAXN];
int dfn[MAXN],rd[MAXN],cnt;
int fa[MAXN][18],d[MAXN];
inline void dfs(int x,int fat) {
dfn[x] = ++ cnt;
da[cnt] = a[x];
fa[x][0] = fat;
d[x] = d[fat] + 1;
for(int i = 1;i <= 17;i ++) fa[x][i] = fa[fa[x][i-1]][i-1];
for(int i = 0;i < g[x].size();i ++) {
if(g[x][i] != fat) {
dfs(g[x][i],x);
}
}
rd[x] = cnt;
return ;
}
inline int lca(int a,int b) {
if(d[a] < d[b]) swap(a,b);
if(d[a] > d[b]) {
for(int i = 17;i >= 0;i --) {
if(d[fa[a][i]] >= d[b]) a = fa[a][i];
}
}
if(a == b) return a;
for(int i = 17;i >= 0;i --) {
if(fa[a][i] ^ fa[b][i]) {
a = fa[a][i];
b = fa[b][i];
}
}
return fa[a][0];
} signed main() {
n = read();m = read();
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
for(int i = 2;i <= n;i ++) {
s = read();o = read();
g[s].push_back(o);
g[o].push_back(s);
}
dfs(1,0);
maketree(n);
for(int i = 1;i <= m;i ++) {
k = read();
if(k == 1) {
root = read();
}
else if(k == 2) {
s = read();o = read();k = read();
int lc = lca(s,o);
if(d[lca(root,lc)] < d[lc]) {
addtree(dfn[lc],rd[lc],(LL)k);
}
else if(lca(root,s) == root || lca(root,o) == root) {
addtree(1,n,(LL)k);
}
else {
int lt = lca(root,s),rt = lca(root,o);
int fn = root;
for(int i = 17;i >= 0;i --) {
if(d[fa[fn][i]] > max(d[lt],d[rt])) {
fn = fa[fn][i];
}
}
addtree(1,dfn[fn] - 1,(LL)k);
addtree(rd[fn] + 1,n,(LL)k);
}
}
else if(k == 3) {
s = read();
if(lca(s,root) ^ s) {
printf("%lld\n",findtree(dfn[s],rd[s]));
}
else if(s ^ root) {
int fn = root;
for(int i = 17;i >= 0;i --) {
if(d[fa[fn][i]] > d[s]) fn = fa[fn][i];
}
printf("%lld\n",findtree(1,dfn[fn] - 1) + findtree(rd[fn] + 1,n));
}
else printf("%lld\n",findtree(1,n));
}
}
return 0;
}

Jamie and Tree (dfs序 + 最近公共祖先LCA)的更多相关文章

  1. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  2. POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)

    POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...

  3. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  4. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  5. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  6. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  7. leetcode 236. 二叉树的最近公共祖先LCA(后序遍历,回溯)

    LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百 ...

  8. Codeforces Round #200 (Div. 1)D. Water Tree dfs序

    D. Water Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343/problem/ ...

  9. poj 3321 Apple Tree dfs序+线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K       Description There is an apple tree outsid ...

随机推荐

  1. UVA471 Magic Numbers 题解

    1.题目 题意很简单:输入n,枚举所有的a,b,使得 (1)满足a/b=n. (2)满足a,b各个位上的数字不相同. 2.思路 (1)对于被除数,要满足各个位上的数字,显然最大枚举到987654321 ...

  2. JZOJ 5409 Fantasy & NOI 2010 超级钢琴 题解

    其实早在 2020-12-26 的比赛我们就做过 5409. Fantasy 这可是紫题啊 题目大意 给你一个序列,求长度在 \([L,R]\) 区间内的 \(k\) 个连续子序列的最大和 题解 如此 ...

  3. electron-vue 项目启动动态获取配置文件中的后端服务地址

    前言 最近的项目迭代中新增一个需求,需要在electron-vue 项目打包之后,启动exe 可执行程序的时候,动态获取配置文件中的 baseUrl 作为服务端的地址.electron 可以使用 no ...

  4. JS:逗号运算符

    逗号运算符: 会把逗号隔开的表达式全部执行 最后一个运行的表达式的结果就是逗号运算符的结果   例: var a = (1, 2, 3, 4, 5, 6); console.log(a); //6 隐 ...

  5. 『忘了再学』Shell流程控制 — 36、for循环介绍

    目录 1.for循环介绍 2.示例 语法一举例: 语法二举例: 3.for循环总结 4.练习:批量解压缩脚本 方式一:批量解压缩 方式二:批量解压缩 1.for循环介绍 for循环是固定循环,也就是在 ...

  6. Nginx工作模式

    Master-Worker模式 1.Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程.2.接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理 ...

  7. 驳"一切不谈考核的管理都是扯淡"

    一.引子 以我个人的从业经验认为,研发人员的量化考核,始终是一个世界难题.正巧不久前在园子里看到了"一切不谈考核的管理都是扯淡!"一文(下面简称为"扯淡"),该 ...

  8. ESXI启用本地登录和SSH服务连接功能,使用Xshell连接

    1.选中Troubleshoot Options进行SSH服务配置 2.开启本地登录功能 3.开启远程连接功能 4.本地登录修改SSH服务允许基于密码登录 默认无法用密码登录ssh服务,只支持基于ke ...

  9. Sentry的安装、配置、使用

    前言 上一篇文章介绍了ExceptionLess这个日志收集系统:ExceptionLess的安装.配置.使用 由于ExceptionLess官方提供的客户端只有.Net/.NetCore平台和js的 ...

  10. 造!又有新的生产力语言了「GitHub 热点速览 v.22.30」

    作者:HelloGitHub-小鱼干 你还记得那些 PHP 开发都去哪了吗?转 Golang 了!移动端现在流行什么?Flutter 编程.现在谷歌带着新的生产力语言来了,Carbon,代号:C++ ...