题意

给定一棵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. Django之ORM数据库增删改查

    总结:ORM的 查.增.删.改 - 查 - client - 有一个展示页面(xxx_show.html) - 这一个页面一输入执行后,get请求向server端发送 - 这个展示页面有添加按钮.删除 ...

  2. WPF学习(一) - XAML

    Window.Grid.TextBox.Button等,都叫元素 xaml文档中,<>用来定义标签,标签可以用来描述元素或元素的属性,如: <Window> <Windo ...

  3. Ajax :六个全局事件

    加载请求: .ajaxStart() 和 .ajaxstop() $(document).ajaxStart(function(){ $('.loading').show(); }).ajaxStop ...

  4. Nginx——在Windows环境下安装(一)

    下载 Nginx是开源软件,用户可以访问 http://nginx.org/ 网站获取源码包或Windows二进制文件下载.其中1.13.x版本为开发版本,1.12.0版本为稳定版本.开发版本分支会较 ...

  5. php报错权限设置

    <?php //禁用错误报告 error_reporting(0); //报告运行时错误 error_reporting(E_ERROR | E_WARNING | E_PARSE); //报告 ...

  6. 操作Map

    ///操作Map Map<String,Object> userInfo = new HashMap(); userInfo.put("uid", adUserEnti ...

  7. canvas 连线曲线图封装

    $.fn.hChart=function (opt) { var setting=$.extend({ className:'', data:[] },opt); var tbody=this; va ...

  8. libcudnn (R5) not found in library path

    环境:Ubuntu 18.04 +  Torch7 + cuda10 在运行使用cudnn的lua程序的时候产生错误: /home/majiabiao/torch/: /home/majiabiao/ ...

  9. C实现JAVA类似ArrayList的静态链接库

    文件结构: ArrayList.h:头文件 ArrayList.c:实现头文件中的功能 ArrayListTest.c:测试 ArrayList.h 头文件的基本框架: #ifndef _ARRAYL ...

  10. c++ 子类构造函数初始化及父类构造初始化

    我们知道,构造方法是用来初始化类对象的.如果在类中没有显式地声明构造函数,那么编译器会自动创建一个默认的构造函数:并且这个默认的构造函数仅仅在没有显式地声明构造函数的情况下才会被创建创建. 构造函数与 ...