题意

给定一棵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. Redis-3-string类型

    Redis-3-string类型 标签(空格分隔): redis set key value [ex 秒数] / [px 毫秒数] [nx] /[xx] mset key value key valu ...

  2. _itoa进制转换

    #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <stdio.h> void main() { int ...

  3. POJ 3261 后缀数组+二分

    思路: 论文题- 二分+对后缀分组 这块一开始不用基数排序 会更快的(其实区别不大) //By SiriusRen #include <cstdio> #include <cstri ...

  4. C#调用webservice(一)

    最近一直在搞网络编程,这篇是关于webservice的,准备写两篇例子这篇是实现手机号码归宿地查询,下篇准备写实现机票查询. 这个网站(http://www.webxml.com.cn/zh_cn/i ...

  5. MySQL学习(二)——SQL语句创建删除修改以及中文乱码问题

    一.对数据库的操作 1.创建一个库 create database 库名; 创建带有编码的:create database 库名 character set 编码; 查看编码:show create ...

  6. HTML基础——网站首页显示页面

    1.表格标签: border设置边框,align设置位置(居中等),bgcolor设置背景颜色,cellspacing设置边框之间的空隙,cellpadding设置边框与里面内容的间距. table表 ...

  7. 我的Java历程_写出这个数

    lzJava基础进行中,今天偶然间看到的一个题目: 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字.如下代码: import java.util.*;public class Ma ...

  8. python3 之 Ellipsis

    在翻django 代码的时候无意中看到的, 主要还是在注解时候使用 官方参考:https://docs.python.org/3/library/constants.html#Ellipsis 注意: ...

  9. ansible搭建mysql主主模式

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)等优点,实现了批量系统配置.批量程序部署.批量运行命 ...

  10. WPF打字机效果

    public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TypewriteTex ...