#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
#define mid ((l+r)>>1)
#define left_son root<<1,l,mid
#define right_son root<<1|1,mid+1,r
#define ll long long
int n,m;
int e,begin[maxn],next[maxn],to[maxn],w[maxn];
struct segment_tree{
ll sum,mark,l,r;
}tree[maxn<<2];
int son[maxn],id[maxn],father[maxn],cnt,deep[maxn],size[maxn],top[maxn],_map[maxn];
inline void add(int x,int y){
to[++e] = y;
next[e] = begin[x];
begin[x] = e;
}
inline void pushup(int root){
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 build(int root,int l,int r){
tree[root].l = l;
tree[root].r = r;
tree[root].mark = 0;
if(l == r){
tree[root].sum = w[_map[l]];
return;
}
build(left_son);
build(right_son);
pushup(root);
}
inline void update(int root,int l,int r,int al,int ar,ll k){
if(al > r || ar < l)return;
if(al <= l && ar >= r){
tree[root].mark += k;
tree[root].sum += k*(r-l+1);
return;
}
pushdown(root);
update(left_son,al,ar,k);
update(right_son,al,ar,k);
pushup(root);
}
inline ll query(int root,int l,int r,int al,int ar){
if(al > r || ar < l)return 0;
if(al <= l && ar >= r)return tree[root].sum;
pushdown(root);
return query(left_son,al,ar)+query(right_son,al,ar);
}
inline ll query_range(int x,int y){
ll ans = 0;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]])swap(x,y);
ans += query(1,1,cnt,id[top[x]],id[x]);
x = father[top[x]];
}
if(deep[x] > deep[y])swap(x,y);
ans += query(1,1,cnt,id[x],id[y]);
return ans;
}
inline void dfs1(int x,int fa,int dep){
deep[x] = dep;
father[x] = fa;
size[x] = 1;
int maxson = -1;
for(int i = begin[x];i;i = next[i]){
int y = to[i];
if(y == fa)continue;
dfs1(y,x,dep+1);
size[x] += size[y];
if(size[y] > maxson)son[x] = y,maxson = size[y];
}
}
inline void dfs2(int x,int ntop){
id[x] = ++cnt;
top[x] = ntop;
_map[id[x]] = x;
if(!son[x])return;
dfs2(son[x],ntop);
for(int i = begin[x];i;i = next[i]){
int y = to[i];
if(y == father[x] || y == son[x])continue;
dfs2(y,y);
}
}
int main(){
cin>>n>>m;
for(int i = 1;i <= n;i++)scanf("%d",&w[i]);
for(int i = 1,u,v;i < n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,cnt);
while(m--){
ll x,y,dispose;
scanf("%lld%lld",&dispose,&x);
if(dispose == 1){
scanf("%lld",&y);
update(1,1,cnt,id[x],id[x],y);
}
if(dispose == 2){
scanf("%lld",&y);
update(1,1,cnt,id[x],id[x]+size[x]-1,y);
}
if(dispose == 3)printf("%lld\n",query_range(1,x));
}
return 0;
}

  

[HAOI2015]树上操作-树链剖分的更多相关文章

  1. bzoj4034[HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6163  Solved: 2025[Submit][Stat ...

  2. bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Stat ...

  3. 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树

    [BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...

  4. BZOJ4034 [HAOI2015]树上操作 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...

  5. P3178 [HAOI2015]树上操作 树链剖分

    这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...

  6. BZOJ4034[HAOI2015]树上操作——树链剖分+线段树

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...

  7. bzoj 4034: [HAOI2015]树上操作——树链剖分

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  8. BZOJ 4034[HAOI2015]树上操作(树链剖分)

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...

  9. bzoj4034 [HAOI2015]树上操作——树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034 树剖裸题: 一定要注意 long long !!! update 的时候别忘了 pus ...

随机推荐

  1. HttpServletRequest get

    假设客户端请求的地址:http://localhost:8082/TestReq/MyServlet/username=李雷&age=20 request.getRequestURL http ...

  2. sklearn.neural_network.MLPClassifier参数说明

    目录 sklearn.neural_network.MLPClassifier sklearn.neural_network.MLPClassifier MLPClassifier(hidden_la ...

  3. IntelliJ IDEA 2018.3 重大升级,哪些功能打动了你?

    前言 2018.11.28 IntelliJ IDEA 2018.3 正式版发布.对于一个忠实爱好者,迫不及待的我下载了最新版本来体验下.而且 IDEA 今年的第三次重大更新提供了不容错过的显著功能! ...

  4. OracleSql语句学习(一)

    --SQL语句本身是不区分大小写的,每个关键字用空格隔开,为了增加可读性,退出所有关键字--全部大写,非关键字都小写SELECT SYSDATE FROM dual--创建表CREATE TABLE ...

  5. php函数 array_diff

    array_diff ( array $array1 , array $array2 [, array $... ] ) : array 对比 array1 和其他一个或者多个数组,返回在 array ...

  6. js计算两个日期的月份差?

    //两个日期 var date1 = '2013-03-26'; var date2 = '2011-01-10'; // 拆分年月日 date1 = date1.split('-'); // 得到月 ...

  7. elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    一.ES Client 简介 1. ES是一个服务,采用C/S结构 2. 回顾 ES的架构 3. ES支持的客户端连接方式 3.1 REST API ,端口 9200 这种连接方式对应于架构图中的RE ...

  8. Lodop打印表格带页头页尾 高度是否包含页头页尾

    通过设置TableHeightScope,可以实现对ADD_PRINT_TABLE,表格带页头页尾,查看本博客另一篇博文:Lodop打印表格带页头页尾 自动分页每页显示头尾 超文本超过打印项高度,会自 ...

  9. 使用chrome开发者工具中的network面板测量网站网络性能

    前面的话 Chrome 开发者工具是一套内置于Google Chrome中的Web开发和调试工具,可用来对网站进行迭代.调试和分析.使用 Network 面板测量网站网络性能.本文将详细介绍chrom ...

  10. python之序列化模块、双下方法(dict call new del len eq hash)和单例模式

    摘要:__new__ __del__ __call__ __len__ __eq__ __hash__ import json 序列化模块 import pickle 序列化模块 补充: 现在我们都应 ...