题意

给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和。
计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v。 2 给定两个整数l,r,计算sum[l]+sum[l+1]+….+sum[r-1]+sum[r]
N<=10^5,M<=10^5

题解

每一个块中统计sum[i]的和,这个直接求出DFS序维护树状数组nlogn统计就行。

然后询问时对于一个整块直接加上我们统计的sum[i]的和,然后对于边角余料,我们用树状数组求就行。

修改时我们要维护树状数组直接位置上加(x-v[i])就行。

然后我们要维护块的和,就需要把和加上块中i的祖先数(包含i)*(x-v[i])。

所以我们预处理出f[i][j]代表第i块中j(包括j)的祖先数。这个dfs中用一个数组记录祖先情况(进入时加上自己,推出时减掉自己),对于每个点扫一遍每个块统计就行。

然后这题要用unsigned long long 然后也不能全开,会MLE

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
int cnt,head[N];
int size[N],id[N],tot;
int num[],block[N],f[][N];
unsigned long long sum[],a[N],tr[N],ans,v[N];
int n,m,R[],L[],Block,root;
struct edge{
int to,nxt;
}e[N*];
void add(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs1(int u,int fa){
size[u]=;
id[u]=++tot;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dfs1(v,u);
size[u]+=size[v];
}
}
void dfs2(int u,int fa){
num[block[u]]++;
for(int i=;i<=block[n];i++){
f[i][u]+=num[i];
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dfs2(v,u);
}
num[block[u]]--;
}
int lowbit(int x){
return x&-x;
}
void update(int x,unsigned long long w){
for(int i=x;i<=n;i+=lowbit(i)){
tr[i]+=w;
}
}
unsigned long long query(int x){
unsigned long long tmp=;
for(int i=x;i;i-=lowbit(i)){
tmp+=tr[i];
}
return tmp;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%llu",&v[i]);
}
for(int i=;i<=n;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u==){
root=v;
continue;
}
add(u,v);
add(v,u);
}
dfs1(root,);
for(int i=;i<=n;i++){
update(id[i],v[i]);
}
for(int i=;i<=n;i++){
a[i]=query(id[i]+size[i]-)-query(id[i]-);
// cout<<i<<" "<<id[i]<<" "<<size[i]<<" "<<a[i]<<endl;
}
Block=sqrt(n);
for(int i=;i<=n;i++){
block[i]=(i-)/Block+;
sum[block[i]]+=a[i];
if(!L[block[i]])L[block[i]]=i;
R[block[i]]=i;
}
dfs2(root,);
while(m--){
int k,x,y;
scanf("%d%d%d",&k,&x,&y);
if(k==){
for(int i=;i<=block[n];i++){
sum[i]+=f[i][x]*(y-v[x]);
}
update(id[x],y-v[x]);
v[x]=y;
}
else{
ans=;
if(block[x]+>=block[y]){
for(int i=x;i<=y;i++){
ans+=query(id[i]+size[i]-)-query(id[i]-);
}
}
else{
for(int i=block[x]+;i<=block[y]-;i++){
ans+=sum[i];
}
for(int i=x;i<=R[block[x]];i++){
ans+=query(id[i]+size[i]-)-query(id[i]-);
}
for(int i=L[block[y]];i<=y;i++){
ans+=query(id[i]+size[i]-)-query(id[i]-);
}
}
printf("%llu\n",ans);
}
}
return ;
}

[bzoj4765]普通计算姬(分块+树状数组+DFS序)的更多相关文章

  1. BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]

    传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...

  2. [BZOJ4765]普通计算姬(分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1725  Solved: 376[Submit][Status][Discus ...

  3. BZOJ 4765: 普通计算姬 (分块+树状数组)

    传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...

  4. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  5. bzoj 4765 普通计算姬(树状数组 + 分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...

  6. 【BZOJ-1103】大都市meg 树状数组 + DFS序

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2009  Solved: 1056[Submit][Sta ...

  7. [luogu P3787][新创无际夏日公开赛] 冰精冻西瓜 [树状数组][dfs序]

    题目背景 盛夏,冰之妖精琪露诺发现了一大片西瓜地,终于可以吃到美味的冻西瓜啦. 题目描述 琪露诺是拥有操纵冷气程度的能力的妖精,一天她发现了一片西瓜地.这里有n个西瓜,由n-1条西瓜蔓连接,形成一个有 ...

  8. HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)

    Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  9. 【BZOJ3653】谈笑风生 离线+树状数组+DFS序

    [BZOJ3653]谈笑风生 Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”. ? 设a 和 ...

随机推荐

  1. JavaScript学习——使用JS实现首页轮播图效果

    1.相关技术 获取元素 document.getElementById(“id 名称”) 事件(onload) 只能写一次并且放到body标签中 定时操作:setInterval(“changeImg ...

  2. .NET深入解析LINQ框架1

    1.LINQ简述 2.LINQ优雅前奏的音符 2.1.隐式类型 (由编辑器自动根据表达式推断出对象的最终类型) 2.2.对象初始化器 (简化了对象的创建及初始化的过程) 2.3.Lambda表达式 ( ...

  3. *hiho 1475 - 数组拆分,dp,由N^2降到NlogN

    题目链接 描述 小Ho得到了一个数组作为他的新年礼物,他非常喜欢这个数组! 在仔细研究了几天之后,小Ho成功的将这个数组拆成了若干段,并且每段的和都不为0! 现在小Ho希望知道,这样的拆分方法一共有多 ...

  4. C语言基础 (2) linux命令

    01.课程回顾 链接 ln 1.txt aaa.txt  硬链接 (两个相互独立 删除一个另外一个还在) ln -s 1.txt aaa.txt软连接 (后面的是快捷方式) 硬链接只能是文件,软连接可 ...

  5. js去掉字符串得第一个字符 、去掉字符串的最后一个字符

    a1 = aa[0].slice(1);  //去掉第一个字符串 a2 = a2.substr(0, a2.length - 1);

  6. camke 参数

    cmake -DCMAKE_INSTALL_PREFIX=/application/mysql-5.5.32 \   -DMYSQL_DATADIR=/application/mysql-5.5.32 ...

  7. 紫书 习题 11-8 UVa 1663 (最大流求二分图最大基数匹配)

    很奇怪, 看到网上用的都是匈牙利算法求最大基数匹配 紫书上压根没讲这个算法, 而是用最大流求的. 难道是因为第一个人用匈牙利算法然后其他所有的博客都是看这个博客的吗? 很有可能-- 回归正题. 题目中 ...

  8. Generator 简介

    Generator 就是一种状态机,封装多个内部状态. 执行 Generator 函数会返回一个遍历器对象(),也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数.返回的遍历器对 ...

  9. 2015 Multi-University Training Contest 1 OO’s Sequence

    OO’s Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  10. RvmTranslator7.1

    RvmTranslator7.1 eryar@163.com RvmTranslator can translate the RVM file exported by AVEVA Plant(PDMS ...