HAOI2015 树上操作
HAOI2015 树上操作
题目描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
输入输出格式
输入格式:
第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式:
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
输入输出样例
5 5 1 2 3 4 5 1 2 1 4 2 3 2 5 3 3 1 2 1 3 5 2 1 2 3 3
6 9 13
说明
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
模板题就不多说啦,http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html 有介绍,我就是看这个懂得
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100000 + 10;
int cnt = 0,n,m,map[maxn],val[maxn],num[maxn],size[maxn],father[maxn],son[maxn],top[maxn],dep[maxn],w[maxn];
vector<int> edges[maxn];
inline void dfs1(int now,int f) {
size[now] = 1;
father[now] = f;
dep[now] = dep[father[now]]+1;
for (size_t i = 0;i < edges[now].size();i++)
if (edges[now][i] != f) {
dfs1(edges[now][i],now);
size[now] += size[edges[now][i]];
if (size[son[now]] < size[edges[now][i]] || !son[now]) son[now] = edges[now][i];
}
}
inline void dfs2(int now,int ntop) {
top[now] = ntop;
num[now] = ++cnt;
map[num[now]] = now;
if (son[now]) dfs2(son[now],ntop);
for (size_t i = 0;i < edges[now].size();i++)
if (edges[now][i] != father[now] && edges[now][i] != son[now]) dfs2(edges[now][i],edges[now][i]);
}
struct seg { long long sum,mark,l,r; } tree[maxn*4];
inline void BuildTree(int l,int r,int root) {
if (l == r) {
tree[root].l = l;
tree[root].r = r;
tree[root].sum = val[map[l]];
tree[root].mark = 0;
return;
}
int mid = l+r>>1;
BuildTree(l,mid,root<<1);
BuildTree(mid+1,r,(root<<1)+1);
tree[root].l = l;
tree[root].r = r;
tree[root].mark = 0;
tree[root].sum = tree[root<<1].sum+tree[(root<<1)+1].sum;
}
inline void pushdown(int root) {
if (tree[root].mark) {
tree[root<<1].mark += tree[root].mark;
tree[root<<1|1].mark += tree[root].mark;
tree[root<<1].sum += tree[root].mark*(tree[root<<1].r-tree[root<<1].l+1);
tree[root<<1|1].sum += tree[root].mark*(tree[root<<1|1].r-tree[root<<1|1].l+1);
tree[root].mark = 0;
}
}
inline void Update(int l,int r,int ql,int qr,int root,long long x) {
if (ql > r || qr < l) return;
if (ql <= l && qr >= r) {
tree[root].mark += x;
tree[root].sum += x*(r-l+1);
return;
}
pushdown(root);
int mid = l+r>>1;
Update(l,mid,ql,qr,root<<1,x);
Update(mid+1,r,ql,qr,root<<1|1,x);
tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
}
inline long long Query(int l,int r,int ql,int qr,int root) {
if (ql > r || qr < l) return 0;
if (ql <= l && qr >= r) return tree[root].sum;
pushdown(root);
int mid = l+r>>1;
return Query(l,mid,ql,qr,root<<1)+Query(mid+1,r,ql,qr,root<<1|1);
}
inline long long QueryEdges(int u,int v) {
int topu = top[u];
int topv = top[v];
long long sum = 0;
while (topu != topv) {
if (dep[topu] < dep[topv]) {
swap(topu,topv);
swap(u,v);
}
sum += Query(1,cnt,num[topu],num[u],1);
u = father[topu];
topu = top[u];
}
if (dep[u] > dep[v]) swap(u,v);
return sum+Query(1,cnt,num[u],num[v],1);
}
int main() {
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i++) scanf("%d",&val[i]);
for (int i = 1,u,v;i < n;i++) {
scanf("%d%d",&u,&v);
edges[u].push_back(v);
edges[v].push_back(u);
}
dfs1(1,0);
dfs2(1,1);
BuildTree(1,cnt,1);
while (m--) {
long long dispose,x,y;
scanf("%lld%lld",&dispose,&x);
if (dispose == 1) {
scanf("%lld",&y);
Update(1,cnt,num[x],num[x],1,y);
} else if (dispose == 2) {
scanf("%lld",&y);
Update(1,cnt,num[x],num[x]+size[x]-1,1,y);
} else if (dispose == 3) printf("%lld\n",QueryEdges(1,x));
}
return 0;
}
HAOI2015 树上操作的更多相关文章
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 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 为根,且树点有边 ...
随机推荐
- 互联网级监控系统必备-时序数据库之Influxdb集群及踩过的坑
上篇博文中,我们介绍了做互联网级监控系统的必备-Influxdb的关键特性.数据读写.应用场景: 互联网级监控系统必备-时序数据库之Influxdb 本文中,我们介绍Influxdb数据库集群的搭建, ...
- mongoDB创建数据库用户
运行mongo.exe >use demo //切换到要创建用户的数据库 >db.createUser({user: "admin",pwd: "admin& ...
- webgl自学笔记——几何图形
3D应用的基础元素: 1.canvas,它是渲染场景的占位符.标准html的canvas元素 2.Objects,这里指的是组成一个场景的所有3d实体.这些实体都由三角形组成.webgl中使用Buff ...
- 两个java项目,跨域访问时,浏览器不能正确解析数据问题
@Controller@RequestMapping(value = "api/item/cat")public class ApiItemCatController { @Aut ...
- 解决IE8下不支持document.getElementsByClassName的方法
在代码前面加如下代码: if (!document.getElementsByClassName) { document.getElementsByClassName = function (clas ...
- pyqt5 在qt designer后以弹窗的方式连接多个UI图形界面
当我们通过pyqt开发时,eric6为我们提供了一个方便的工具:图形化的绘制UI工具--qt designer. 我们可以通过它开发多个UI,然后利用信号-槽工具,将功能代码附着在上面.也可以将多个界 ...
- PPK提供的浏览器类型及版本检测方法
PPK提供的浏览器类型及版本检测方法 一个常用但是被高估的Javascript函数就是浏览器检测.有些时候,你想给出一个说明或者加载一个页面来提示用户,以免使用Safari等浏览器. 使用方法: ...
- Redux源码分析之applyMiddleware
Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...
- JavaScript中数组的方法总结
js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^var arr = new Array();arr[0] = "aaa";arr[1] ...
- CTF比赛中SQL注入的一些经验总结
ctf中sql注入下的一些小技巧 最近花了一点时间总结了各大平台中注入的trick,自己还是太菜了,多半都得看题解,就特此做了一个paper方便总结 注释符 以下是Mysql中可以用到的单行注释符: ...