[bzoj4765]普通计算姬(分块+树状数组+DFS序)
题意
给定一棵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序)的更多相关文章
- BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...
- [BZOJ4765]普通计算姬(分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1725 Solved: 376[Submit][Status][Discus ...
- BZOJ 4765: 普通计算姬 (分块+树状数组)
传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- bzoj 4765 普通计算姬(树状数组 + 分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...
- 【BZOJ-1103】大都市meg 树状数组 + DFS序
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2009 Solved: 1056[Submit][Sta ...
- [luogu P3787][新创无际夏日公开赛] 冰精冻西瓜 [树状数组][dfs序]
题目背景 盛夏,冰之妖精琪露诺发现了一大片西瓜地,终于可以吃到美味的冻西瓜啦. 题目描述 琪露诺是拥有操纵冷气程度的能力的妖精,一天她发现了一片西瓜地.这里有n个西瓜,由n-1条西瓜蔓连接,形成一个有 ...
- HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)
Tree chain problem Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- 【BZOJ3653】谈笑风生 离线+树状数组+DFS序
[BZOJ3653]谈笑风生 Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”. ? 设a 和 ...
随机推荐
- JavaScript中Math常用方法
title: JavaScript中Math常用方法 toc: false date: 2018-10-13 12:19:31 Math.E --2.718281828459045,算数常量e Mat ...
- C# WindowsAPI
Windows是一个强大的操作系统,也会向开发者提供海量的系统API来帮助开发者来完成Windows系统软件的开发工作. 整理的部分Windows API,C#可以直接调用. 1.获取.exe应用程序 ...
- sql 跟踪
目录 1 sql跟踪 1.1 alter session 1.2 DBMS_MONITOR 1.3 DBMS_SESSION 1.4 oradebug模式 1.5 触发器的模式启用sql 跟踪 1.6 ...
- Pharmaceutical的同学们都看过来,关于补码运算的复习相关内容
虽然是全英文的课程,这次总结内容不用英文了. 一般在计算机原理中,对两个操作数进行运算会使用C作为进位的标志位,而V作为溢出的标志位. 一般我们学完计算机原理,都知道正数的原码反码补码都一样,而问题都 ...
- Hibernate框架学习(一)——入门
一.框架是什么 1.框架是用来提高开发效率的 2.封装好了一些功能,我们需要使用这些功能时,调用即可,不需要手动实现 3.框架可以理解成一个半成品的项目,只要懂得如何驾驭这些功能即可 二.hibern ...
- C# AssemblyResolve事件可能不触发
C# AssemblyResolve事件需要引用的dll的“复制本地”属性设置为False,如果为True,可能不会触发这个事件的处理函数. 我想设计一个自动加载分架构的C++/CLI的dll,用到了 ...
- eclipse01
http://blog.csdn.net/luman1991/article/category/6354903
- LNMP升级开启TLSv1.3支持
LNMP升级开启TLSv1.3支持 TLSv1.3版本的优势:https://baijiahao.baidu.com/s?id=1611365293186683991&wfr=spider&a ...
- [NOIP2003提高组]侦探推理
题目:洛谷P1039.Vijos P1106.codevs1089. 题目大意:给你一系列证词,要你求出谁是凶手.具体题目见原题. 解题思路:我们枚举犯人和星期,一个一个进行判断.如果成功则记录答案, ...
- linux下安装jdk跟tomcat
文章参考 https://www.cnblogs.com/geekdc/p/5607100.html Linux服务器安装jdk+tomcat https://baijiahao.baidu ...