题面

题解

我们求它子树的权值和,一般用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. Docker容器手动安装mysql(国内镜像)

    Docker手动安装mysql 1.创建centos镜像的容器 [root@localhost Tools]# docker run -i -d -h zabbix --name zabbix -p ...

  2. 开发工具-Base64编码/解码

    更新日志 2022年6月10日 新增链接. https://toolb.cn/base64

  3. GIF录制工具下载

    GIF录制工具(GifCam)下载地址: https://files.cnblogs.com/files/blogs/747754/GifCam.rar

  4. C语言学习之我见-strncat()可调整的字符串拼接函数

    strncat()函数,用于两个字符串的拼接. (1)函数原型 char * strncat(char * Dest,const char * Source,size_t _Count)` (2)头文 ...

  5. 3D还原货拉拉女孩身亡真相,这一环值得反思!

    货拉拉女孩跳车身亡的消息,让人惋惜又震惊.司机多次偏离原始路线,女孩最终选择跳车,结果不幸身亡. 货拉拉女孩跳车真相被3D还原 有人质疑平台监管不力,造成如此惨剧,有人吐槽企业压榨员工,司机绕路是不得 ...

  6. Javaweb-Servlet学习

    1.Servlet简介 Servlet就是sun公司开发动态web的一门技术 Sun在这些API中提供一个借口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤: 编写一个 ...

  7. 关于各种Vue UI框架中加载进度条的正确使用

    这里拿MUSE UI 中的进度条举例 <mu-circular-progress :size="40" class="icon" v-if="i ...

  8. Linux系统安全配置

    1.物理安全 硬件服务器,关闭从CD/DVD等这些方面的软启动方式.同时也可以设置BIOS密码,并且要有限制访问的策略与各类流程管控. 还可以禁用USB设备来达到安全的目的: centos7x 安装d ...

  9. centos 7安装zabbix

    1 升级系统组件到最新版本 yum -y update 2 关闭 SELinux sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" / ...

  10. python——5行代码采集3000+上市公司信息

    毕业季也到了找工作的季节了,很多小伙伴都会一家一家的公司去看,这得多浪费时间啊.今天用Python教大家怎么采集公司的信息,相信大家会很喜欢这个教程的,nice! 基本环境配置 版本:Python3 ...