【bzoj4765】普通计算姬(双重分块)
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4765
这道题已经攒了半年多了。。。因为懒,一直没去写。。。所以今天才把这道题写出来。。。
如果是要维护区间权值和、子树权值和,都可以用线段树/树状数组轻松解决。但是这道题要维护的是子树权值和的区间和,这就比较难搞了。
当需要维护一些看起来很难直接维护的信息时,我们一般会想到分块。于是考虑这样的分块:按编号把每√n个节点划分为一块,维护每一块所有节点的sum值的和,然后再维护每个节点的sum值。单节点的sum可以用树状数组/线段树维护,但为了降低时间复杂度,我们可以用分块维护dfs序的区间和的前缀和,这样的单节点修改复杂度为O(√n),单节点查询复杂度为O(1)。
时间复杂度:修改操作O(√n),查询操作O(√n),总时间复杂度O((n+m)√n)。
具体实现细节:维护第一层分块(即sum值的和)时可以在dfs遍历树时一个数组记录每个节点修改时对每个块的贡献,然后修改时直接统计贡献修改块的值就行了;第二层分块(即单节点的sum)时可以分别维护块的前缀和与每个节点在所在块内的前缀和,查询时把两部分加起来就行了。
另外,答案要开unsigned long long!
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-18
inline ll read()
{
ll tmp=; char c=getchar(),f=;
for(;c<''||''<c;c=getchar())if(c=='-')f=-;
for(;''<=c&&c<='';c=getchar())tmp=(tmp<<)+(tmp<<)+c-'';
return tmp*f;
}
using namespace std;
struct edge{
int to,nxt;
}e[];
int fir[],l[],r[],pos[];
ull sum1[],sum2[];
int a[],tmp[];
ull sum[];
int w[][];
int n,m,size,tot=,root;
void addedge(int x,int y){e[tot].to=y; e[tot].nxt=fir[x]; fir[x]=tot++;}
void dfs(int now,int fa)
{
if(now!=root){
for(int i=;i*size<n;i++)w[now][i]=w[fa][i];
}
++w[now][now/size]; l[now]=tot; pos[now]=tot++;
for(int i=fir[now];~i;i=e[i].nxt)
if(e[i].to!=fa)dfs(e[i].to,now);
r[now]=tot-;
}
void add(int x,int k)
{
int i,id=pos[x]/size;
a[x]+=k;
for(i=id;i*size<n;i++)sum1[i]+=k;
for(i=pos[x];i<(id+)*size&&i<n;i++)sum2[i]+=k;
for(i=;i*size<n;i++)sum[i]+=1ll*w[x][i]*k;
}
ull getsum(int x)
{
if(x<)return ;
else return sum2[x]+(x<size?:sum1[x/size-]);
}
ull query(int L,int R)
{
int i,idL=L/size,idR=R/size;
ull ans=;
if(idL==idR){
for(i=L;i<=R;i++)ans+=getsum(r[i])-getsum(l[i]-);
}
else{
for(i=idL+;i<idR;i++)ans+=sum[i];
for(i=L;i<(idL+)*size&&i<n;i++)ans+=getsum(r[i])-getsum(l[i]-);
for(i=idR*size;i<=R;i++)ans+=getsum(r[i])-getsum(l[i]-);
}
return ans;
}
int main()
{
int i;
n=read(); m=read(); size=(int)sqrt(n);
for(i=;i<n;i++)tmp[i]=read();
for(i=;i<n;i++)fir[i]=-;
for(i=;i<=n;i++){
int x=read(),y=read();
if(!x)root=y-;
else addedge(x-,y-),addedge(y-,x-);
}
tot=; dfs(root,-);
for(i=;i<n;i++)add(i,tmp[i]);
for(i=;i<=m;i++){
int op=read(),x=read(),y=read();
if(op==)add(x-,y-a[x-]);
else printf("%llu\n",query(x-,y-));
}
return ;
}
又臭又长
【bzoj4765】普通计算姬(双重分块)的更多相关文章
- [bzoj4765]普通计算姬(分块+树状数组+DFS序)
题意 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 ...
- BZOJ4765 普通计算姬(分块+树状数组)
对节点按编号分块.设f[i][j]为修改j号点对第i块的影响,计算f[i][]时dfs一遍即可.记录每一整块的sum.修改时对每一块直接更新sum,同时用dfs序上的树状数组维护子树和.查询时累加整块 ...
- bzoj4765: 普通计算姬 (分块 && BIT)
最近一直在刷分块啊 似乎感觉分块和BIT是超级棒的搭档啊 这道题首先用dfs预处理一下 得到每一个sum值 此时查询是O(1)的 (前缀和乱搞什么的 但是修改需要O(n) (需要修改该节点所有祖先的 ...
- BZOJ4765: 普通计算姬
BZOJ4765: 普通计算姬 题目描述 传送门 题目分析 求的和非常奇怪,不具有连续性,所有上树的数据结构全死了. 考虑分块,思考对于一段连续的询问区间可以直接询问整块,零散块可以在树上dfs序暴力 ...
- BZOJ_4765_普通计算姬_分块+dfs序+树状数组
BZOJ_4765_普通计算姬_分块 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些 .普通计算机能 ...
- [BZOJ4765]普通计算姬(分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1725 Solved: 376[Submit][Status][Discus ...
- 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...
- [bzoj4765]普通计算姬——分块
Brief Description 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权 值和.支持下列两种操作: 1 给定两个整数u,v, ...
- BZOJ 4765 普通计算姬 (分块 + BIT)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1547 Solved: 329[Submit][Status][Discus ...
- bzoj 4765 普通计算姬 dfs序 + 分块
题目链接 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能 ...
随机推荐
- 用js判断页面是否加载完成
这可以通过用document.onreadystatechange的方法来监听状态改变, 然后用document.readyState == “complete”判断是否加载完成. 可以采用2个div ...
- X明X源面试题《三》
本文转自自zhangxh_Doris 昨天(05.23)下午去参加了明源软件的暑期实习宣讲+笔试,第一次听说这个行业,行业和笔试风格完全不一样啊,5道行测智力题+1个问答+ 斐波那契数列 + 洗牌算法 ...
- zookeeper安装步骤
zookeeper安装步骤 百度搜索:zookeeper 进入后点击下载: 进入到下载的页面 英文: 中文: 进入版本列表: 进入后复制该链接, 在linux执行wget下载: wget https: ...
- dfs-求连通块
状态:若为W则继续搜索 import java.util.Scanner; public class Main { static int n,m; static char[][] field; sta ...
- 封装AFNetworking
用了一下AFNetworking感觉比ASIHttprequest 真心好用一些,因为我还是个初学者吧,很多ASIHttprequest 的功能还没有用到,与ASIHttprequest 不用的是AF ...
- rpm命令相关命令运用实例
1) 挂载光盘文件到/media目录 2) 进去/media目录下的Packages目录 3) 查看系统已安装的所有rpm包 4) 查看系统是否安装dhcp软件包 5,安装dhcp软件包 6) 查看d ...
- mui 视频播放
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- Meteor工作目录的划分
现在说明一下Meteor的工作目录是这样划分的,但是在说明之前 做个约定,以免后面造成混淆或错误. 我们通过 meteor create API-002-Core创建meteor工程后,那么就会有一 ...
- LeetCode-11-6
1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a ...
- ES集群性能调优链接汇总
1. 集群稳定性的一些问题(一定量数据后集群变得迟钝) https://elasticsearch.cn/question/84 2. ELK 性能(2) — 如何在大业务量下保持 Elasticse ...