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. SVN代码的回滚二

    SVN代码的回滚: 不丢失新建的文件,获得最新的SVN版本控制.TortoiseSVN-ShowLog-选中你要回滚的版本-右键-Export,之后将修改的文件覆盖到你的最新版本,commit即可. ...

  2. Mac上安装node.js

    1.下载node for mac并一路默认安装 2.测试成功否 3.copy this file to test(save as javascript file) var http = require ...

  3. Xcode7创建的项目添加启动图有问题?

    在Xcode7下创建的项目,由于某个原因,Xcode7添加启动图有点不一样.Xcode7与Xcode6不一样的地方在于:Xcode6的LaunchScreen.xib改成了LaunchScreen.s ...

  4. android studio使用说明

    一.学习的基本配置文档,搞好各种参数的基本配置,熟练使用. C:\Program Files\Java\jdk1.7.0_09\bin   二.problems meet in weather and ...

  5. 给vps设置ssh供爬墙使用

    在服务器上建一个 username : 添加用户:useradd -s /bin/false username,将用户的shell设置成/bin/false.这样用户就无法与系统进行交互. 设置密码: ...

  6. pre标签避免一行过长打破格局

    pre{ white-space:pre-wrap; word-wrap:break-word; word-break:break-all }

  7. 使用C#改变鼠标的指针形状

    1.在一个无标题的窗体中用MOUSEMOVE事件判断鼠标坐标是否到达窗体的边缘,如果是的话将鼠标指针改为可调整窗体大小的双向箭头. private   void   Form1_MouseMove(o ...

  8. 从log4j日志无缝迁移至logback

    ogback对比log4j的有点在此就不赘述了. 由于在项目的原有代码中,大量的日志生成是通过log4j实现的,新的代码希望通过logback的方式生成日志,同时希望将老的代码在不修改的情况下直接将日 ...

  9. Linux常用指令---ps(查看进程)

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  10. 数据挖掘系列(2)--关联规则FpGrowth算法

    上一篇介绍了关联规则挖掘的一些基本概念和经典的Apriori算法,Aprori算法利用频繁集的两个特性,过滤了很多无关的集合,效率提高不少,但是我们发现Apriori算法是一个候选消除算法,每一次消除 ...