【HAOI2015】树上操作
(题面来自洛谷)
题目描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
数据范围:N <= 1e5
分析:简化版的ETT。建立括号序列,操作1、3都很容易解决。为了实现操作2,给序列上的点打标记,表示这里存储的是原节点权值的正/负值。用线段树维护区间和,上推时分别合并正负节点数,区间修改时每个线段树节点值\(sum+=val*(pos-neg)\),这样就实现了正负节点的区分操作。同时要求移植子树就变成了ETT的模板题,用Splay/FHQ维护即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
const int maxn(100010);
typedef long long LL;
using namespace std;
int n, m;
LL wt[maxn];
int head[maxn], etop;
struct E {
int to, nxt;
} edge[maxn<<1];
inline void insert(int u, int v) {
edge[++etop] = (E) {v, head[u]};
head[u] = etop;
}
int fst[maxn], sec[maxn], tmr;
LL dat[maxn<<1];
bool cat[maxn<<1];
void dfs(int u, int pre) {
fst[u] = ++tmr;
dat[tmr] = wt[u];
cat[tmr] = 1;
for (int i = head[u], v; i; i = edge[i].nxt) {
if ((v = edge[i].to) == pre) continue;
dfs(v, u);
}
sec[u] = ++tmr;
dat[tmr] = -wt[u];
cat[tmr] = 0;
return;
}
namespace Seg_tree {
#define lc (nd<<1)
#define rc ((nd<<1)|1)
#define mid ((l + r) >> 1)
struct node {
LL sum;
int pos, neg;
friend node operator + (node a, node b) {
return (node) {a.sum + b.sum, a.pos + b.pos, a.neg + b.neg};
}
friend node operator * (node a, LL b) {
return (node) {a.sum + b * (a.pos-a.neg), a.pos, a.neg};
}
} seg[maxn<<3];
LL tag[maxn<<3];
inline void update(int nd) {
seg[nd] = seg[lc] + seg[rc];
}
inline void put_tag(int nd, LL val) {
seg[nd] = seg[nd] * val;
tag[nd] += val;
}
inline void push_down(int nd) {
put_tag(lc, tag[nd]);
put_tag(rc, tag[nd]);
tag[nd] = 0;
}
void build(int nd, int l, int r) {
if (l == r) {
seg[nd] = (node) {dat[l], cat[l], !cat[l]};
return;
}
build(lc, l, mid);
build(rc, mid+1, r);
update(nd);
}
void add(int nd, int l, int r, int ql, int qr, LL val) {
if (l >= ql && r <= qr) {
put_tag(nd, val);
return;
}
if (r < ql || l > qr) return;
push_down(nd);
add(lc, l, mid, ql, qr, val);
add(rc, mid+1, r, ql, qr, val);
update(nd);
}
LL query(int nd, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) {
return seg[nd].sum;
}
if (r < ql || l > qr) return 0;
push_down(nd);
return query(lc, l, mid, ql, qr) + query(rc, mid+1, r, ql, qr);
}
} using namespace Seg_tree;
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%lld", &wt[i]);
int u, v;
for (int i = 1; i < n; ++i) {
scanf("%d %d", &u, &v);
insert(u, v), insert(v, u);
}
dfs(1, 0);
build(1, 1, 2*n);
int opt;
while (m--) {
scanf("%d %d", &opt, &u);
if (opt == 3) {
printf("%lld\n", query(1, 1, 2*n, 1, fst[u]));
continue;
}
scanf("%d", &v);
if (opt == 1) {
add(1, 1, 2*n, fst[u], fst[u], v);
add(1, 1, 2*n, sec[u], sec[u], v);
} else add(1, 1, 2*n, fst[u], sec[u], v);
}
return 0;
}
【HAOI2015】树上操作的更多相关文章
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...
- HAOI2015 树上操作
HAOI2015 树上操作 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根 ...
- bzoj千题计划242:bzoj4034: [HAOI2015]树上操作
http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<io ...
- bzoj4034[HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6163 Solved: 2025[Submit][Stat ...
- 树剖||树链剖分||线段树||BZOJ4034||Luogu3178||[HAOI2015]树上操作
题面:P3178 [HAOI2015]树上操作 好像其他人都嫌这道题太容易了懒得讲,好吧那我讲. 题解:第一个操作和第二个操作本质上是一样的,所以可以合并.唯一值得讲的点就是:第二个操作要求把某个节点 ...
- P3178 [HAOI2015]树上操作
P3178 [HAOI2015]树上操作 思路 板子嘛,其实我感觉树剖没啥脑子 就是debug 代码 #include <bits/stdc++.h> #define int long l ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6779 Solved: 2275[Submit][Stat ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
随机推荐
- iOS 14 egret 游戏卡顿问题分析和部分解决办法
现象 总体而言,iOS 14 渲染性能变差,可以从以下三个测试看出. 测试1:简单demo,使用egret引擎显示3000个图(都是同一个100*100 png 纹理),逐帧做旋转.(博客园视频播放可 ...
- Go的第一个Hello程序 简简单单 - 快快乐乐
Go的第一个Hello程序 简简单单 - 快快乐乐 JERRY_Z. ~ 2020 / 10 / 29 转载请注明出处!️ 目录 Go的第一个Hello程序 简简单单 - 快快乐乐 一.Go程序开发基 ...
- 【转载】HPL与HPCG测试(一)
来源:HPL与HPCG测试 (一) 一.HPL与HPCG 简介 1.HPL HPL 即 High Performance Linpack,它是针对现代并行计算集群的测试工具.用户不修改测试程序,通过调 ...
- Linux 网络编程的5种IO模型:异步IO模型
Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...
- typeerror object of type ‘decimal‘ is not json serializable jsonify
当使用flask的jsonify返回json数据时,由于数据库有些字段类型使用decimal,而jsonify无法处理 解决方案 导入下面的包即可解决 pip install simplejson
- python构造函数和析构函数
构造函数和析构函数 关注公众号"轻松学编程"了解更多. 1.构造方法的使用 很多类都倾向于将对象创建为有初始化状态.因此类可以定义一个名为__init__()的特殊方法(构造方 ...
- 【17】进大厂必须掌握的面试题-50个Angular面试
我们整理了一份主要的Angular面试问题清单,分为三部分: 角度面试问题–初学者水平 角度面试问题–中级 角度面试问题–高级 初学者水平–面试问题 1.区分Angular和AngularJS. 特征 ...
- php 之批量生成 mysql 语句 注释
工作需要 需要更新 所有表的注释 不影响原结构之上进行更新 <?php class Ceshi extends CI_Controller{ function __construct() { p ...
- MySQL全面瓦解9:查询的排序、分页相关
概述 数据库中的数据直接呈现出来一般不是我们想要的,所以我们上两节演示了如何对数据进行过滤的方法.除了对数据进行过滤, 我们可能还需要对数据进行排序,比如想从列表中了解消费最高的项,就可能需要对金额字 ...
- python菜鸟教程学习1:背景性学习
https://www.runoob.com/python3/python3-intro.html 优点 简单 -- Python 是一种代表简单主义思想的语言.阅读一个良好的 Python 程序就感 ...