题面

题解

我们求它子树的权值和,一般用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. 对互斥事件和条件概率的相互理解《考研概率论学习之我见》 -by zobol

    1.从条件概率来定义互斥和对立事件 2.互斥事件是独立事件吗? 3.每个样本点都可以看作是互斥事件,来重新看待条件概率 一.从条件概率来定义互斥和对立事件 根据古典概率-条件概率的定义,当在" ...

  2. 名校AI课推荐 | UC Berkeley《人工智能导论》

    深度学习具备强感知能力但缺乏一定的决策能力,强化学习具备决策能力但对感知问题束手无策,因此将两者结合起来可以达到优势互补的效果,为复杂系统的感知决策问题提供了解决思路. 今天我们推荐这样一门课程--U ...

  3. react native 0.6x 在创建项目时,CocoaPods 的依赖安装步骤卡解决方案

    前言 你需要做两件事 gem换源 pod repo 换源 实战 如果你已经成功安装了CocoaPods.那么这里你需要卸载它.gem换源1. 卸载CocoaPods 查看gem安装的东西 gem li ...

  4. SAP BDC 调用中 金额格式转换

    在BDC调用中,由于用户设置不同,导致金额.日期等字段的输入格式不正确.此处给出 自创 金额转换FM 并配有 调用方式. function zgm_conver_cuur. *"------ ...

  5. 论文阅读 Exploring Temporal Information for Dynamic Network Embedding

    10 Exploring Temporal Information for Dynamic Network Embedding 5 link:https://scholar.google.com.sg ...

  6. 02 CSS块级元素和行内元素

    02 CSS块级元素和行内元素 划分依据:根据标签内部可以存放的元素内容不同进行划分,它与CSS样式无关. 要先了解这个 得先了解 什么是容器级别的标签和文本级? 容器级标签 什么是容器级标签? 内部 ...

  7. MYSQL中IF IN语句

    以下代码摘自后台管理系统中的一部分SQL语句: 当取数状态为1或2时,才展示取数时间,否则,取数时间展示为空 当申报状态为2.3.4或5时,才展示申报时间,否则,申报时间展示为空 select A.Q ...

  8. 使用Win自带的远程工具连接Linux

    网上教程一大堆,我这边只简单记录一下,主要是黑屏问题,和剪贴板问题.Win连接Linux,一般都是使用的xrdp, 如果是使用的旧版本的Ubuntu,建议先装一下xfce桌面,gnome桌面一般连不起 ...

  9. GET 和 POST 请求的区别与安全性

    超文本传输协议( HTTP )是用于启用客户端与服务器之间的通信,其中 GET 请求和 POST 请求是则是 HTTP 方法中最为常用的两种.那么这 GET 和 POST 的区别到底是什么呢?两者是否 ...

  10. 微信小程序使用echarts/数据刷新重新渲染/图层遮挡问题

    1.微信小程序使用echarts,首先下载echarts并导入小程序项目中,因小程序后期上线对文件大小有要求,所以建议进行定制下载导入可减少文件大小占比,也可以下载以前旧版本文件比较小的应付使用 下载 ...