Jamie and Tree (dfs序 + 最近公共祖先LCA)
题面

题解
我们求它子树的权值和,一般用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)的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- leetcode 236. 二叉树的最近公共祖先LCA(后序遍历,回溯)
LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百 ...
- 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/ ...
- poj 3321 Apple Tree dfs序+线段树
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Description There is an apple tree outsid ...
随机推荐
- sort是不稳定排序
今天才知道sort是不稳定的,WA了一个点. sort()排序不是稳定排序,sort是主要用到了快速排序(平均时间复杂度为O(nlogn)),还结合了插入排序(时间复杂度为O(n2))和堆排序(时间复 ...
- react native 0.6x 在创建项目时,CocoaPods 的依赖安装步骤卡解决方案
前言 你需要做两件事 gem换源 pod repo 换源 实战 如果你已经成功安装了CocoaPods.那么这里你需要卸载它.gem换源1. 卸载CocoaPods 查看gem安装的东西 gem li ...
- 《ECMAScript 6 入门》【二、变量的解构赋值】(持续更新中……)
前言: 让我们看下es6的新语法解构,跟模式匹配类似.一.数组的解构赋值 举个例子给多个变量赋值的写法: var a =1;var b =2;var c =3; 需要写多个变量特别麻烦,我们先使用以前 ...
- ABAP CDS - Annotations 注解
Syntax ... annotation[.annotation1[.annotation2]][:value] ... Effect Annotation that can be specifi ...
- CesiumJS 2022^ 源码解读[6] - 三维模型(ModelExperimental)新架构
目录 1. ModelExperimental 的缓存机制 1.1. 缓存池 ResourceCache 1.2. 缓存对象的键设计 ResourceCacheKey 2. 三维模型的加载与解析 2. ...
- sql server2016 数据库日志 清空语句
/*1.查询数据库日志文件名称*/--TC_MES_DEV为数据库名--这里的 数据库日志名,可以用以下注释的语句进行查询(_log那个)USE [TC_MES_DEV]GOSELECT file_i ...
- NC202498 货物种类
NC202498 货物种类 题目 题目描述 某电商平台有 \(n\) 个仓库,编号从 \(1\) 到 \(n\) . 当购进某种货物的时候,商家会把货物分散的放在编号相邻的几个仓库中. 我们暂时不考虑 ...
- Android Studio 的初次使用
记录我第一次使用Android Studio时遇到的问题以及一些简单的笔记. 我所使用的是Android Studio 2.2版本 遇到的问题 创建一个Hello World!项目无疑是相当简单的,我 ...
- leetcode教程系列——Binary Tree
tree是一种常用的数据结构用来模拟真实物理世界里树的层级结构.每个tree有一个根(root)节点和指向其他节点的叶子(leaf)节点.从graph的角度看,tree也可以看作是有N个节点和N-1个 ...
- IDEA的项目结构和IDEA的HelloWord
IDEA首次驱动 1. 选择不导入任何设置,点击 OK 2. 选择 Create New Project 3. 点击 new 按钮,配置安装的 JDK9 版本 选择 JDK9 目录,点击确定 4. 不 ...