bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 4352 Solved: 1387
[Submit][Status][Discuss]
Description
Input
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
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
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。
思路:由于有3的操作,很容易想到树链剖分,2怎么办?
对于树链剖分来说,其子树中的节点,也是连续的,所以找子树中编号最大的;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-14
#define bug(x) cout<<"bug"<<x<<endl;
const int N=1e5+,M=1e6+,inf=1e9+;
const ll INF=1e18+,mod=; ///数组大小
struct edge
{
int v,next;
} edge[N<<];
int head[N<<],edg,id,n;
/// 树链剖分 int fa[N],dep[N],son[N],siz[N]; // fa父亲,dep深度,son重儿子,siz以该点为子树的节点个数
int a[N],ran[N],top[N],tid[N],mx[N]; // tid表示边的标号,top通过重边可以到达最上面的点,ran表示标记tid
void init()
{
memset(son,-,sizeof(son));
memset(head,-,sizeof(head));
edg=;
id=;
} void add(int u,int v)
{
edg++;
edge[edg].v=v;
edge[edg].next=head[u];
head[u]=edg;
} void dfs1(int u,int fath,int deep)
{
fa[u]=fath;
siz[u]=;
dep[u]=deep;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==fath)continue;
dfs1(v,u,deep+);
siz[u]+=siz[v];
if(son[u]==-||siz[v]>siz[son[u]])
son[u]=v;
}
} void dfs2(int u,int tp)
{
tid[u]=mx[u]=++id;
top[u]=tp;
ran[tid[u]]=u;
if(son[u]==-)return;
dfs2(son[u],tp),mx[u]=max(mx[u],mx[son[u]]);
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==fa[u])continue;
if(v!=son[u])
dfs2(v,v),mx[u]=max(mx[u],mx[v]);
}
} struct SGT
{
ll sum[N<<],lazy[N<<];
void pushup(int pos)
{
sum[pos]=sum[pos<<]+sum[pos<<|];
}
void pushdown(int pos,int l,int r)
{
if(lazy[pos])
{
int mid=(l+r)>>;
lazy[pos<<]+=lazy[pos];
lazy[pos<<|]+=lazy[pos];
sum[pos<<]+=lazy[pos]*(mid-l+);
sum[pos<<|]+=lazy[pos]*(r-mid);
lazy[pos]=;
}
}
void build(int l,int r,int pos)
{
lazy[pos]=;
if(l==r)
{
sum[pos]=a[ran[l]];
return;
}
int mid=(l+r)>>;
build(l,mid,pos<<);
build(mid+,r,pos<<|);
pushup(pos);
}
void update(int L,int R,ll c,int l,int r,int pos)
{
if(L<=l&&r<=R)
{
sum[pos]+=c*(r-l+);
lazy[pos]+=c;
return;
}
pushdown(pos,l,r);
int mid=(l+r)>>;
if(L<=mid)update(L,R,c,l,mid,pos<<);
if(R>mid) update(L,R,c,mid+,r,pos<<|);
pushup(pos);
}
ll query(int L,int R,int l,int r,int pos)
{
if(L<=l&&r<=R)return sum[pos];
pushdown(pos,l,r);
int mid=(l+r)>>;
ll ans=;
if(L<=mid)ans+=query(L,R,l,mid,pos<<);
if(R>mid)ans+=query(L,R,mid+,r,pos<<|);
return ans;
}
}tree; ll up(int l,int r)
{
ll ans=;
while(top[l]!=top[r])
{
if(dep[top[l]]<dep[top[r]])swap(l,r);
ans+=tree.query(tid[top[l]],tid[l],,n,);
l=fa[top[l]];
}
if(dep[l]<dep[r])swap(l,r);
ans+=tree.query(tid[r],tid[l],,n,);
return ans;
} int main()
{
init();
int q;
scanf("%d%d",&n,&q);
for(int i=; i<=n; i++)
scanf("%d",&a[i]);
for(int i=; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(,-,);
dfs2(,);
tree.build(,n,);
while(q--)
{
int t,x;
scanf("%d%d",&t,&x);
if(t==)
{
ll z;
scanf("%lld",&z);
tree.update(tid[x],tid[x],z,,n,);
}
else if(t==)
{
ll z;
scanf("%lld",&z);
tree.update(tid[x],mx[x],z,,n,);
}
else
printf("%lld\n",up(,x));
}
return ;
}
bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树的更多相关文章
- BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
随机推荐
- [转载]Oracle 游标使用全解
这个文档几乎包含了oracle游标使用的方方面面,全部通过了测试 -- 声明游标:CURSOR cursor_name IS select_statement --For 循环游标--(1)定义游标- ...
- CAT Caterpillar ET is really a exceptional obd2 solution
As a excellent obd2 solutions,Heavy Duty Diagnostic CAT Caterpillar ET Diagnostic Adapter features a ...
- 计算概论(A)/基础编程练习1(8题)/1:大象喝水
#include<stdio.h> int main() { ; // n < 100 scanf("%d", &n); // 循环遍历判断 再进行平方和 ...
- linux+apache+nginx实现,反向代理动静分离
在我们开发的过程中,一定会遇到,负载均衡方面的问题.下面我们,做一个小例子:使用nginx+apache实现反向代理,动静分离. 这里apache.php.nginx的安装就不做赘述了,不懂的朋友可以 ...
- Docker学习笔记之搭建 Java Web 项目运行环境
0x00 概述 Java Web 泛指以 Java 程序为基础向外提供 Web 服务的技术及相关工具,狭义上来说,我们也可以说 Java Web 是由 Servlet 程序提供的 Web 服务. 对我 ...
- TCP/IP 最常见的错误原因码 (errno)列表
对于在基于 UNIX 的环境中的 TCP/IP 用户,下表列出了某些最常见的错误原因码 (errno).它不是完整的错误列表.可以在文件 /usr/include/sys/errno.h 中找到 Er ...
- python之路-day1-if...else...流程判断
判断输入的用户名:#Author:zww _username = "zww" _password = " username = input("username: ...
- js的匿名函数 和普通函数
匿名函数在声明时不用带上函数名, 可以把匿名函数当作一个function类型的值来对待 声明一个普通的函数 function func() { ... } 可以认为和var func = functi ...
- [c/c++] programming之路(9)、运算优先级
一.运算优先级 二.条件运算符(表达式1?表达式2:表达式3) 当式1正确时,取式2的值:否则,取式3的值 三.格式字符 #include<stdio.h> #include<std ...
- Codeforces Round #439 (Div. 2) Problem E (Codeforces 869E) - 暴力 - 随机化 - 二维树状数组 - 差分
Adieu l'ami. Koyomi is helping Oshino, an acquaintance of his, to take care of an open space around ...