Description

  有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

  操作 1 :把某个节点 x 的点权增加 a 。
  操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

Input

  第一行包含两个整数 N, M 。表示点数和操作数。

  接下来一行 N 个整数,表示树中节点的初始权值。
  接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
  再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
  作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

Output

  对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

Sample Input

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

Sample Output

6
9
13

HINT

  对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

Source

  鸣谢bhiaibogf提供

Solution

  树链剖分,用线段树维护点权;对子树的修改就是区间修改,因为其dfs序是连续的

 #include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, nxt;
}e[];
struct point
{
int val, siz, fa, son, dfn, top;
}p[];
struct seg
{
long long val, lazy;
}a[];
int fst[], ptot; void addedge(int i, int u, int v)
{
e[i] = (edge){v, fst[u]}, fst[u] = i;
} void DFS1(int u)
{
p[u].siz = ;
for(int i = fst[u]; i; i = e[i].nxt)
if(p[u].fa != e[i].v)
{
p[e[i].v].fa = u;
DFS1(e[i].v);
p[u].siz += p[e[i].v].siz;
if(p[e[i].v].siz > p[p[u].son].siz)
p[u].son = e[i].v;
}
} void DFS2(int u, int top)
{
p[u].dfn = ++ptot, p[u].top = top;
if(p[u].son) DFS2(p[u].son, top);
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != p[u].fa && e[i].v != p[u].son)
DFS2(e[i].v, e[i].v);
} void push_up(int o, int l, int r)
{
a[o].val = a[o << ].val + a[o << | ].val;
a[o].val += a[o].lazy * (r - l + );
} void push_down(int o, int l, int r)
{
int mid = (l + r) >> ;
if(l == r) return;
if(a[o].lazy)
{
a[o << ].lazy += a[o].lazy;
a[o << ].val += a[o].lazy * (mid - l + );
a[o << | ].lazy += a[o].lazy;
a[o << | ].val += a[o].lazy * (r - mid);
a[o].lazy = ;
}
} void update(int o, int l, int r, int ql, int qr, int val)
{
int mid = (l + r) >> ;
push_down(o, l, r);
if(ql <= l && r <= qr)
{
a[o].lazy += val;
a[o].val += (long long)val * (r - l + );
return;
}
if(ql <= mid) update(o << , l, mid, ql, qr, val);
if(mid < qr) update(o << | , mid + , r, ql, qr, val);
push_up(o, l, r);
} long long query(int o, int l, int r, int ql, int qr)
{
int mid = (l + r) >> ;
long long ans = ;
push_down(o, l, r);
if(ql <= l && r <= qr) return a[o].val;
if(ql <= mid) ans = query(o << , l, mid, ql, qr);
if(mid < qr) ans += query(o << | , mid + , r, ql, qr);
return ans;
} int main()
{
int n, m, u, v, op, x, val;
long long ans;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i)
scanf("%d", &p[i].val);
for(int i = ; i < n; ++i)
{
scanf("%d%d", &u, &v);
addedge(i << , u, v);
addedge(i << | , v, u);
}
DFS1(), DFS2(, );
for(int i = ; i <= n; ++i)
update(, , n, p[i].dfn, p[i].dfn, p[i].val);
while(m--)
{
scanf("%d", &op);
if(op == )
{
scanf("%d%d", &x, &val);
update(, , n, p[x].dfn, p[x].dfn, val);
}
else if(op == )
{
scanf("%d%d", &x, &val);
update(, , n, p[x].dfn, p[x].dfn + p[x].siz - , val);
}
else
{
scanf("%d", &x);
ans = ;
while(x)
{
ans += query(, , n, p[p[x].top].dfn, p[x].dfn);
x = p[p[x].top].fa;
}
printf("%lld\n", ans);
}
}
return ;
}

[BZOJ4034] [HAOI2015] T2 (树链剖分)的更多相关文章

  1. Bzoj 4034: [HAOI2015]T2 树链剖分,子树问题,dfs序

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1841  Solved: 598[Submit][Status] ...

  2. BZOJ 4034: [HAOI2015]T2( 树链剖分 )

    树链剖分...子树的树链剖分序必定是一段区间 , 先记录一下就好了 ------------------------------------------------------------------ ...

  3. JZYZOJ1539[haoi2015]T2 树链剖分

    http://172.20.6.3/Problem_Show.asp?id=1539 在学校的OJ又写了一次,RE了好多次,原来haoi的时候这道题需要开栈+快读,裸数据结构30分,加上快读50分.o ...

  4. bzoj4034 树上操作 树链剖分+线段树

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

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

    题目链接  BZOJ4034 这道题树链剖分其实就可以了. 单点更新没问题. 相当于更新 [f[x], f[x]]这个区间. f[x]表示树链剖分之后每个点的新的标号. 区间更新的话类似DFS序,求出 ...

  6. bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1536  Solved: 508[Submit][Status] ...

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

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

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

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

  9. BZOJ 4034 [HAOI2015]T2(树链剖分)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4034 [题目大意] 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 有 M 个 ...

随机推荐

  1. 解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程

    解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程 昨天开发人员跟我说,执行一个sql语句后,大约花了10分钟,好不容易有一个结果,但是报了一个ora-01652错误,查阅 ...

  2. 128. Longest Consecutive Sequence

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  3. 217. Contains Duplicate

    题目: Given an array of integers, find if the array contains any duplicates. Your function should retu ...

  4. 【C语言】02-基本数据类型

    跟其他语言一样,C语言中用变量来存储计算过程使用的值,任何变量都必须先定义类型再使用.为什么一定要先定义呢?因为变量的类型决定了变量占用的存储空间,所以定义变量类型,就是为了给该变量分配适当的存储空间 ...

  5. Java-ServletRequestEvent-ServletRequestAttributeEvent

    /** * Events of this kind indicate lifecycle * events for a ServletRequest. * The source of the even ...

  6. Scrapy基础(七)————图片的简单下载

    scrapy 提供了自动下载图片到本地的功能,通过项目管道设置 一: 在setting 文件中ITEM_PIPELINE添加: 'scrapy.pipelines.images.ImagesPipel ...

  7. R语言的ARIMA模型预测

    R通过RODBC连接数据库 stats包中的st函数建立时间序列 funitRoot包中的unitrootTest函数检验单位根 forecast包中的函数进行预测 差分用timeSeries包中di ...

  8. Linux内核(16) - 高效学习Linux内核

    世界悲结束了,章鱼哥也退役了,连非诚勿扰中的拜金女也突然的少了很多.这本<Linux内核修炼之道>在卓越.当当.china-pub上也已经开卖了,虽然是严肃文学,但为了保证流畅性,大部分文 ...

  9. 高德地图sdk的AMapNavi.getInstance为null解决办法

    问题,动态库没有全部导入,之前我只放到了armeabi下,可是没想到我手机是armeabi-v7a的. 最近做Android项目,先用的是百度地图,可是后来发现百度地图没有提供地图的View点击事件( ...

  10. OpenCV中的SURF算法介绍

    SURF:speed up robust feature,翻译为快速鲁棒特征.首先就其中涉及到的特征点和描述符做一些简单的介绍: 特征点和描述符 特征点分为两类:狭义特征点和广义特征点.狭义特征点的位 ...