【HAOI2015】树上操作(树链剖分)
题面
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
数据范围:
对于30%的数据,N,M<=1000。
对于50%的数据,N,M<=100000且数据随机。
对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。
题解
依旧是很显然的树链剖分,要用longlong存答案
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define MAX 101000
#define lson (now<<1)
#define rson ((now<<1)|1)
inline int read()
{
register int x=0,t=1;
register char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-'){t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*t;
}
struct Line
{
int v,next;
}e[MAX*2];
struct Node
{
long long v,lazy;
}c[MAX*5];
int h[MAX],cnt=1,tim,V[MAX];
int dfn[MAX],low[MAX],f[MAX],hson[MAX],line[MAX],size[MAX],top[MAX];
int N,Q,dep[MAX];
inline void Add(int u,int v)
{
e[cnt]=(Line){v,h[u]};
h[u]=cnt++;
}
void DFS1(int u,int ff)
{
size[u]=1;f[u]=ff;hson[u]=0;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==ff)continue;
DFS1(v,u);
if(size[v]>size[hson[u]])hson[u]=v;
size[u]+=size[v];
}
}
void DFS2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim;line[tim]=u;
if(hson[u])DFS2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==f[u]||v==hson[u])continue;
DFS2(v,v);
}
low[u]=tim;
}
void Build(int now,int l,int r)
{
if(l==r){c[now].v=V[line[l]];return;}
int mid=(l+r)>>1;
Build(lson,l,mid);Build(rson,mid+1,r);
c[now].v=c[lson].v+c[rson].v;
}
void pushdown(int now,int l,int r)
{
c[now].v+=1LL*(r-l+1)*c[now].lazy;
c[lson].lazy+=c[now].lazy;
c[rson].lazy+=c[now].lazy;
c[now].lazy=0;
}
void update(int now,int l,int r,int al,int ar,int w)
{
if(l==al&&r==ar){c[now].lazy+=w;return;}
int mid=(l+r)>>1;
c[now].v+=1LL*(ar-al+1)*w;
if(ar<=mid)update(lson,l,mid,al,ar,w);
else if(al>mid)update(rson,mid+1,r,al,ar,w);
else {update(lson,l,mid,al,mid,w);update(rson,mid+1,r,mid+1,ar,w);}
}
long long Query(int now,int l,int r,int al,int ar)
{
pushdown(now,l,r);
if(l==al&&r==ar)return c[now].v;
int mid=(l+r)>>1;
if(ar<=mid)return Query(lson,l,mid,al,ar);
if(al>mid)return Query(rson,mid+1,r,al,ar);
return Query(lson,l,mid,al,mid)+Query(rson,mid+1,r,mid+1,ar);
}
long long Answer(int u)
{
int v=1,tp1=top[u],tp2=top[v];
long long ans=0;
while(tp1!=tp2)
{
if(dep[tp1]<dep[tp2])
{
swap(tp1,tp2);
swap(u,v);
}
ans+=Query(1,1,N,dfn[tp1],dfn[u]);
u=f[tp1];tp1=top[u];
}
if(dep[u]<dep[v])swap(u,v);
ans+=Query(1,1,N,dfn[v],dfn[u]);
return ans;
}
int main()
{
N=read();Q=read();
for(int i=1;i<=N;++i)V[i]=read();
for(int i=1;i<N;++i)
{
int u=read(),v=read();
Add(u,v);Add(v,u);
}
DFS1(1,0);DFS2(1,1);
Build(1,1,N);
while(Q--)
{
int kk=read();
if(kk==1)
{
int a=read(),b=read();
update(1,1,N,dfn[a],dfn[a],b);
}
if(kk==2)
{
int a=read(),b=read();
update(1,1,N,dfn[a],low[a],b);
}
if(kk==3)
{
int a=read();
printf("%lld\n",Answer(a));
}
}
return 0;
}
【HAOI2015】树上操作(树链剖分)的更多相关文章
- bzoj4034[HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6163 Solved: 2025[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...
- BZOJ4034 [HAOI2015]树上操作 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...
- P3178 [HAOI2015]树上操作 树链剖分
这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...
- BZOJ4034[HAOI2015]树上操作——树链剖分+线段树
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- BZOJ 4034[HAOI2015]树上操作(树链剖分)
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...
- bzoj4034 [HAOI2015]树上操作——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034 树剖裸题: 一定要注意 long long !!! update 的时候别忘了 pus ...
- [HAOI2015]树上操作-树链剖分
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; #define mid ((l+r)>> ...
随机推荐
- LeetCode - 776. Split BST
Given a Binary Search Tree (BST) with root node root, and a target value V, split the tree into two ...
- XAMPP简介、安转、使用
虽然没有写Mac安装方法及使用, 但方法也都大相径庭, 殊途同归而已. XAMPP简介 XAMPP是一款开源.免费的网络服务器软件,经过简单安装后,就可以在个人电脑上搭建服务器环境.本文为大家介绍Wi ...
- GitHub中开启二次验证Two-factor authentication,如何在命令行下更新和上传代码
最近在使用GitHub管理代码,在git命令行管理代码时候遇到一些问题.如果开起了二次验证(Two-factor authentication两个要素认证),命令行会一直提示输入用户名和密码.查找了一 ...
- [译]前端JS面试题汇总 Part 1(事件委托/this关键字/原型链/AMD与CommonJS/自执行函数)
原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questio ...
- Spring中的@scope注解
默认是单例模式,即scope="singleton".另外scope还有prototype.request.session.global session作用域.scope=&quo ...
- 一不小心把Mysql数据库的root的账号的权限给弄没啦,该怎么办
别急啊,现在只要你还能连接到Mysql,就问题不大! 首先,连接道Mysql,这里用Navicat进行讲解. 说明:root@localhost和root@127.0.0.1不是一个账号,也不是一回事 ...
- DxPackNet 5.视频高质量的压缩和传输
DxPackNet 对视频的压缩和解压也提供了很好的支持,且系统不需要装第三方解码器哦~ 主要用到了 IxVideoEncoder 视频编码器 和 IxVideoDecoder 两个接口 这里只做简 ...
- lower_bound()返回值
lower_bound()函数实现功能就是二分查找,函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置.如果所有元素都小于val,则 ...
- Codeforces103D - Time to Raid Cowavans
Portal Description 给出长度为\(n(n\leq3\times10^5)\)的序列\(\{a_n\}\),进行\(q(q\leq3\times10^5)\)次询问:给出\(x,y\) ...
- hive:排序分析函数
基本排序函数 语法: rank()over([partition by col1] order by col2) dense_rank()over([partition by col1] order ...