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 。
 
 
正解:树链剖分
解题报告:
  链剖裸题。
  但是我居然调试了很久!!!先是迷之RE,结果是细节问题。。。然后是迷之WA,结果是中间变量没开long long
  多么痛的领悟。。。
 
 
 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
const int MAXM = ;
int n,m;
int ecnt,cnt;
int first[MAXN],to[MAXM],next[MAXM],id[MAXN],pre[MAXN],last[MAXN],deep[MAXN],father[MAXN],size[MAXN],son[MAXN],top[MAXN];
int num[MAXN];
LL qx,qy;
int ql,qr;
LL ans; struct node{
LL add;
LL val;
}t[MAXN*]; inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline void dfs1(int x,int fa) {
size[x] = ;
for(int i = first[x];i;i = next[i]) {
int v = to[i];
if(v != fa){
father[v] = x; deep[v] = deep[x]+;
dfs1(v,x);
size[x] += size[v]; if(size[v] > size[son[x]]) son[x] = v;
}
}
} inline void dfs2(int x,int fa){
id[x] = ++cnt; pre[cnt]=x; if(son[x]!=) top[son[x]]=top[x],dfs2(son[x],x);
for(int i = first[x];i;i = next[i]){
int v = to[i];
if(v != fa && v != son[x]) {
top[v]=v;
dfs2(v,x);
}
}
last[x] = cnt;
} inline void build(int root,int l,int r){
if(l == r) { t[root].val = num[pre[l]]; return ; }
int mid = (l + r)/; int lc = root*,rc = lc+;
build(lc,l,mid); build(rc,mid+,r);
t[root].val = t[lc].val + t[rc].val;
} inline void update(int root,int l,int r){
if(ql <= l && qr >= r) { t[root].add += qy; t[root].val += qy*(r-l+); }
else{
int mid = (l + r)/;
int lc = root*,rc = lc + ;
if(ql <= mid) update(lc,l,mid); if(qr > mid) update(rc,mid+,r);
t[root].val = t[lc].val + t[rc].val;
t[root].val += t[root].add*(r-l+);
}
} inline void query(int root,int l,int r,LL lei){
if(ql <= l && qr >= r) {
ans += t[root].val;
ans += (LL)lei*(LL)(r-l+);
return ;
}
int mid = (l+r)/; int lc = root*,rc = lc+;
if(ql <= mid) query(lc,l,mid,lei+t[root].add); if(qr > mid) query(rc,mid+,r,lei+t[root].add);
} inline void work(int x){
ans=;
int f1 = top[x];
while(f1!=) {
ql=id[f1]; qr=id[x];
query(,,n,);
x=father[f1]; f1=top[x];
}
ql=; qr=id[x]; query(,,n,);
printf(OT"\n",ans);
} inline void solve(){
n = getint(); m = getint();
for(int i=;i<=n;i++) num[i] = getint();
int x,y;
for(int i = ;i < n;i++) {
x = getint(); y = getint();
next[++ecnt] = first[x]; first[x] = ecnt; to[ecnt] = y;
next[++ecnt] = first[y]; first[y] = ecnt; to[ecnt] = x;
} deep[]=; dfs1(,);
top[]=; dfs2(,);
build(,,n);
int ljh;
for(int i = ;i <= m;i++) {
ljh = getint();
if(ljh == ){
qx = id[getint()]; qy = getint();
ql=qx; qr=qx;
update(,,n);
}
else if(ljh == ){
x = getint(); qy = getint();
qr = last[x]; ql = id[x];
update(,,n);
}
else{
qx=getint(); work(qx);
}
}
} int main()
{
solve();
return ;
}

BZOJ4034 T2的更多相关文章

  1. bzoj4034: [HAOI2015]T2

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2684  Solved: 843 Description 有一 ...

  2. 【BZOJ4034】T2(树链剖分)

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

  3. BZOJ4034——[HAOI2015]T2

    1.题目大意:用一个数据结构支持树的点修改和子树修改.树上路径和 2.分析:树链剖分裸题 #include <cstdio> #include <cstdlib> #inclu ...

  4. [BZOJ4034] [HAOI2015] T2 (树链剖分)

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

  5. 【DFS序】【线段树】bzoj4034 [HAOI2015]T2

    分开维护树的入栈序和出栈序,用两棵线段树.回答时就是用一颗的减去另一棵的. #include<cstdio> #include<algorithm> using namespa ...

  6. 【bzoj4034】[HAOI2015]T2

    siz[v]表示以v为根的子树的节点数 top[v]表示v所在的重链的顶端节点 fa[v]表示v的父亲 pos[v]表示v的父边标号 mx[v]表示v的子树中边的标号最大的那条边 参考:http:// ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. [Noip2016]蚯蚓 D2 T2 队列

    [Noip2016]蚯蚓 D2 T2 Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯 ...

  9. T2 Func<in T1,out T2>(T1 arg)

    委托调用方法的4种方式. using System; using System.Collections.Generic; namespace ConsoleApplication1 { delegat ...

随机推荐

  1. LYK 快跑!(LYK别打我-)(话说LYK是谁)

    LYK 快跑!(run) Time Limit:5000ms Memory Limit:64MB 题目描述 LYK 陷进了一个迷宫! 这个迷宫是网格图形状的. LYK 一开始在(1,1)位置, 出口在 ...

  2. emberjs重写补充类之reopen方法和reopenClass方法

    无需一次性将类定义完全,你可以使用reopen方法来重新打开(reopen)一个类并为其定义新的属性. Person.reopen({ isPerson: true }); Person.create ...

  3. 一些正则验证-JS

    Validation = { textCount: function(field, counter, maxLimit) { var message = $(field).val(); if ($(f ...

  4. [tools]神器notepad++

    1,现象 notepad++编辑sh文件,放入linux后执行会有问题 2,解决: 2.1dos2unix转换文件 2,2 修改notepad++默认字符集 2,快捷键: ctrl+k 单行.多行注释 ...

  5. C语言 文件操作10--配置文件读写

    //配置文件读写项目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include ...

  6. 利用opencv3中的kmeans实现抠图功能

    kmeans算法主要用来实现自动聚类,是一种非监督的机器学习算法,使用非常广泛.在opencv3.0中提供了这样一个函数,直接调用就能实现自动聚类,非常方便. 函数原型: C++: double km ...

  7. Android RotateAnimation详解

    RotateAnimation旋转坐标系为以旋转点为坐标系(0,0)点.x轴为0度,顺时针方向旋转一定的角度.1.RotateAnimation(fromDegrees, toDegrees) [默认 ...

  8. 第三方框架 INTULocationManager 定位的一些方法

    gitub 下载 INTULocationManager #import "INTULocationManager.h" INTULocationManager *locMgr = ...

  9. Operators一句话介绍(RxJava版)

    Cold Observables 在第一个subscriber订阅后才执行事件发送的Observables,默认普通Observables都是这个类型 Cold Observables对于每个订阅的s ...

  10. UITableView和UICollectionView的Cell高度的几种设置方式

    UITableViewCell 1.UITableView的Cell高度默认由rowHeight属性指定一个低优先级的隐式约束 2.XIB中可向UITableViewCell的contentView添 ...