[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 和 ...
随机推荐
- BZOJ 2096 单调队列
思路: 偷懒用的STL //By SiriusRen #include <deque> #include <cstdio> using namespace std; struc ...
- Java 以空格分割字符串
Java中使用类似于 str.split("/"); 的方法可以很方便的实现将一个字符串分割为数组, 但是如果分隔符是一个(或几个)空格呢?? 我们的本能反应或许应该是 str.s ...
- [转帖]关于Xilinx下Micro_Blaze中UartLite232外设的使用
来源:https://blog.csdn.net/shen_you/article/details/78713746
- UVa 12545 Bits Equalizer【贪心】
题意:给出两个等长的字符串,0可以变成1,?可以变成0和1,可以任意交换s中任意两个字符的位置,问从s变成t至少需要多少次操作 先可以画个草图 发现需要考虑的就是 1---0 0---1 ?---0 ...
- ZBrush中Z球(ZSphere和ZSphereⅡ)
ZSphere可以让用户使用干净的拓扑结构快速建立一个基础网格,然后将其塑造成任何形状.ZSphere的强大在于它非常简单,用户可以从一个单一的ZSphere开始,然后轻松地在其上面增加新的ZSphe ...
- n行m列矩阵顺时针填写1~n*m
程序效果图如下: 程序参考代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ...
- 洛谷P3567 [POI2014]KUR-Couriers 主席树
挺裸的,没啥可讲的. 不带修改的主席树裸题 Code: #include<cstdio> #include<algorithm> using namespace std; co ...
- li自定义图标
/*自定义list的图标*/ li{ list-style-image: url(../img/21.JPG); }
- [转载]PyCharm创建.py自动添加文件头注释
转自:https://blog.csdn.net/qq_36482772/article/details/67218214 创建.py文件时 顺便自动添加作者.时间.文件名信息…… mac系统打开编辑 ...
- [洛谷P1892][codevs2597]团伙
题目大意:有n个强盗,他们有这样的关系:1.朋友的朋友是朋友:2.敌人的敌人是朋友. 两个人是朋友,则他们在一个团伙中,是敌人则在不同团伙中. 现在给出一些朋友或敌人的关系,问最多有多少团伙.输入保证 ...