siz[v]表示以v为根的子树的节点数

top[v]表示v所在的重链的顶端节点

fa[v]表示v的父亲

pos[v]表示v的父边标号

mx[v]表示v的子树中边的标号最大的那条边

参考:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

题意:

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

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

第一次写树链剖分。。

 #include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; typedef long long LL; #define N 100010 int id;
int fa[N],siz[N],top[N];
int head[N],pos[N],mx[N],v[N];
LL sum[N<<],add[N<<]; struct Node
{
int to,next;
}e[N<<];
int cnt; int n,m;
int uu,vv; int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} void link(int x,int y)
{
e[++cnt]=(Node){y,head[x]};
head[x]=cnt;
} void dfs(int x)
{
siz[x]=;
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa[x])
{
fa[e[i].to]=x;
dfs(e[i].to);
siz[x]+=siz[e[i].to];
mx[x]=max(mx[x],mx[e[i].to]);
}
} void dfs2(int x,int cha)
{
top[x]=cha;pos[x]=mx[x]=++id;
int k=;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa[x]&&siz[e[i].to]>siz[k])
k=e[i].to;
if(k)
{
dfs2(k,cha);mx[x]=max(mx[x],mx[k]);
}
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa[x]&&e[i].to!=k)
{
dfs2(e[i].to,e[i].to);
mx[x]=max(mx[x],mx[e[i].to]);
}
} void pushup(int now)
{
sum[now]=sum[now<<]+sum[now<<|];
} void pushdown(int nowl,int nowr,int now)
{
if (nowl==nowr)
return;
int mid=(nowl+nowr)>>;
LL t=add[now];
add[now]=;
add[now<<]+=t;
add[now<<|]+=t;
sum[now<<]+=t*(mid-nowl+);
sum[now<<|]+=t*(nowr-mid);
} void update(int nowl,int nowr,int now,int l,int r,LL d)
{
if (add[now])
pushdown(nowl,nowr,now);
if (nowl==l && nowr==r)
{
add[now]+=d;
sum[now]+=(nowr-nowl+)*d;
return ;
}
int mid=(nowl+nowr)>>;
if (l<=mid)
update(nowl,mid,now<<,l,min(r,mid),d);
if (r>mid)
update(mid+,nowr,now<<|,max(l,mid+),r,d);
pushup(now);
} LL query(int nowl,int nowr,int now,int l,int r)
{
if (add[now])
pushdown(nowl,nowr,now);
if (nowl==l && nowr==r)
return sum[now];
int mid=(nowl+nowr)>>;
LL ans=;
if (l<=mid)
ans+=query(nowl,mid,now<<,l,min(mid,r));
if (r>mid)
ans+=query(mid+,nowr,now<<|,max(mid+,l),r);
return ans;
} LL query(int x)
{
LL ans=;
while (top[x]!=)
{
ans+=query(,n,,pos[top[x]],pos[x]);
x=fa[top[x]];
}
ans+=query(,n,,,pos[x]);
return ans;
} int main()
{
n=read(),m=read();
for (int i=;i<=n;i++)
v[i]=read();
for (int i=;i<n;i++)
{
uu=read(),vv=read();
link(uu,vv);
link(vv,uu);
}
dfs();
dfs2(,);
for (int i=;i<=n;i++)
update(,n,,pos[i],pos[i],v[i]);
int askd,x,a;
while (m--)
{
askd=read(),x=read();
if (askd==)
{
a=read();
update(,n,,pos[x],pos[x],a);
}
if (askd==)
{
a=read();
update(,n,,pos[x],mx[x],a);
}
if (askd==)
printf("%lld\n",query(x));
}
return ;
}

【bzoj4034】[HAOI2015]T2的更多相关文章

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

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

  2. 【bzoj4034】[HAOI2015]树上操作

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

  3. 【BZOJ4036】[HAOI2015]按位或 FWT

    [BZOJ4036][HAOI2015]按位或 Description 刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal的or ...

  4. 【BZOJ4033】[HAOI2015]树上染色 树形DP

    [BZOJ4033][HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染 ...

  5. 【NOIP2016】DAY1 T2 天天爱跑步

    [NOIP2016]DAY1 T2 天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时 ...

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

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

  7. 【BZOJ4034】【HAOI2015】树上操作

    题目请自行查阅传送门. 典型的树剖题,线段树维护操作,记一下子树在线段树内范围即可. 时间复杂度:\( O(m \log^{2} n) \) #include <stdio.h> #def ...

  8. 【SRM】649 t2

    题意 一个数列\(A\),数的范围均在\([0, 2^N-1]\)内,求一个\(B\),使得新生成的数列\(C\)中逆序对最多(\(C_i = A_i xor B\)),输出最多的逆序对.(\(|A| ...

  9. 【nowcoder】 4th T2 区间

    题目链接:https://www.nowcoder.com/acm/contest/175/B 当你为时间复杂度挠头的时候 别人已经33行拿满分了 #include<cstdio> #in ...

随机推荐

  1. A7. JVM 垃圾回收收集器(GC 收集器)

    [概述] 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现.Java 虚拟机规范中对垃圾收集器应该如何实现没有任何规定,因此不同的厂商.不同版本的虚拟机所提供的垃圾处理器都可能会 ...

  2. nginx配置错误页面

    有时候页面会遇到404页面找不到错误,或者是500.502这种服务端错误,这时候我们可能希望自己定制返回页面,不希望看到默认的或者是内部的错误页面,可以通过nginx配置来实现. 1 50x错误对于5 ...

  3. Broadcasting

    目录 Broadcasting Key idea How to understand? Why broadcasting? Broadcastable? Broadcast VS Tile Broad ...

  4. Reparameterization Trick

    目录 Sample() is not differentiable Reparameterization trick Too Complex Sample() is not differentiabl ...

  5. python视频 神经网络 Tensorflow

    python视频 神经网络 Tensorflow 模块 视频教程 (带源码) 所属网站分类: 资源下载 > python视频教程 作者:smile 链接:http://www.pythonhei ...

  6. 如何使用JDK1.6 API

    如何使用JDK1.6 API-------https://jingyan.baidu.com/article/54b6b9c0e39a102d583b47d5.html  

  7. Leetcode 211.添加与搜索单词

    添加与搜索单词 设计一个支持以下两种操作的数据结构: void addWord(word) bool search(word) search(word) 可以搜索文字或正则表达式字符串,字符串只包含字 ...

  8. Leetcode 179.最大数

    最大数 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数. 示例 1: 输入: [10,2] 输出: 210 示例 2: 输入: [3,30,34,5,9] 输出: 9534330 impo ...

  9. 食物(bzoj 3280)

    Description 明明这次又要出去旅游了,和上次不同的是,他这次要去宇宙探险! 我们暂且不讨论他有多么NC,他又幻想了他应该带一些什么东西.理所当然的,你当然要帮他计算携带N件物品的方案数. 他 ...

  10. 「CodePlus 2017 12 月赛」火锅盛宴

    n<=100000种食物,给每个食物煮熟时间,有q<=500000个操作:在某时刻插入某个食物:查询熟食中编号最小的并删除之:查询是否有编号为id的食物,如果有查询是否有编号为id的熟食, ...