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. sublime text 快捷键记录

    sublime常用快捷键 Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑) Ctrl+G 跳转到相应的行 Ctrl+J 合并行(已选择需要合并的多行时) Ctrl ...

  2. 全国绿色计算大赛 模拟赛第一阶段(Python)

    第1关求和 class Task: def getSum(self, num1, num2): sum = 0 for i in range(num1, num2 + 1): while (i != ...

  3. [Python3网络爬虫开发实战] 1.8.3-Scrapy-Splash的安装

    Scrapy-Splash是一个Scrapy中支持JavaScript渲染的工具,本节来介绍它的安装方式. Scrapy-Splash的安装分为两部分.一个是Splash服务的安装,具体是通过Dock ...

  4. virtualbox虚拟机桥接方式网络设置

    一.编辑网卡 cd   /etc/sysconfig/network-scripts 查看本地win10ip及子网掩码: 如果查看到的ip不是192开头的,可以手动设置为192开头的ip 2.设置虚拟 ...

  5. Codeforces Beta Round #19D(Points)线段树

    D. Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  6. 【03】emmet系列之CSS语法

    [01]emmet系列之基础介绍 [02]emmet系列之HTML语法 [03]emmet系列之CSS语法 [04]emmet系列之编辑器 [05]emmet系列之各种缩写   单位: 有几个常用值别 ...

  7. 将Java程序打包成可执行EXE文件的步骤

    需要的工具myeclipse .jar2exe(附上下载地址,直接解压就可以用链接: https://pan.baidu.com/s/1qYPRgXu 密码: wbva) 1.将Java项目导出成.j ...

  8. HDU 5492 Find a path

    Find a path Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID ...

  9. Mongo的Replica Sets (复制集)的配置全过程和心得体会

    http://blog.csdn.net/bloggongchang/article/details/7272403 一.MongoDB Replica Sets(副本集)简单的说就是有自动故障恢复功 ...

  10. [OJ#39]左手右手

    [OJ#39]左手右手 试题描述 有 n 个人,每个人左右手上各写着一个整数.对于编号为 a 的人和编号为 b 的人, a 对 b 的好感度等于 a 左手上写的数字乘 b 右手上写的数字,a 和 b  ...