【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 为根,且树点有边 ...
随机推荐
- ActiveMQ第一个示例
首先先安装ActiveMQ:https://www.cnblogs.com/hejianliang/p/9149590.html 创建Java项目,把 activemq-all-5.15.4.jar ...
- NB-IoT窄带物联网技术的四大优势
NB-IoT是指窄带物联网(Narrow Band -Internet of Things)技术,是IoT领域一个新兴的技术,支持低功耗设备在广域网的蜂窝数据连接,也被叫作低功耗广域网(LPWA) ...
- Ethernaut靶场练习(0-5)
1.Hello Ethernaut 目标: 安装好metamask,熟悉操作命令. 操作过程: 我们先提交一个实例,然后打开游览器F12.然后跟他的提示走. 先输入contract.info(). c ...
- 3.5 MyLinkedList 实现
3.5 MyLinkedList 类的实现 MyLinkedList 将用双链表实现,并且还需要保留该表两端的引用.这将需要三个类 MyLinkedList 类,包含到两端的链.表的大小以及一些方法. ...
- 【QT】子类化QObject+moveToThread实现多线程
往期链接: <QThread源码浅析> <子类化QThread实现多线程> 从往期<QThread源码浅析>可知,在Qt4.4之前,run 是纯虚函数,必须子类化Q ...
- 子线程调用invalidate()产生“Only the original thread that created a view hierarchy can touch its views.”原因分析
目录 1.异常出处 2.从View.invalidate()方法开始分析 3.ViewRootImpl如何与View进行关联:从Activity的setContentView开始分析 3.1 最顶层的 ...
- Java项目——嗖嗖移动业务大厅
嗖嗖移动业务大厅包类(如下图): SosoMgr: 1 package cn.biz; 2 3 import java.util.Scanner; 4 5 import cn.common.Commo ...
- Layui弹出层详解
今天空了学习一下弹出层 还是一步步展示把 首先,layer可以独立使用,也可以通过Layui模块化使用.我个人一直是用的模块化的 所以下面素有的都是基于模块化的. 引入好相关文件就可以开始啦 今天放 ...
- 《.NET 5.0 背锅案》第6集-案发现场回顾:故障情况下 Kubernetes 的部署表现
第1集:验证 .NET 5.0 正式版 docker 镜像问题 第2集:码中的小窟窿,背后的大坑,发现重要嫌犯 EnyimMemcachedCore 第3集-剧情反转:EnyimMemcachedCo ...
- ubuntu安装软件自动交互
在ubuntu下安装软件过程中可能会出现需要你输入密码或者其他的一些交互类的操作,这样在脚本安装的时候就可能出现阻断,这个在ubuntu里面已经考虑到了这个情况,以前我在安装这个的时候,通过的是脚本传 ...