BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
题意:
一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和
只有我这种不会分块的沙茶不会做这道题吗?
说一点总结:
子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原序列分块,$sum_i$为一块的答案
查询很显然了,整块用$sum$,非整块暴力查子树
修改的话,预处理$f[i][j]$为点$j$对第$i$块的贡献,一遍$dfs$就可以预处理出来
然后,我的$BIT$用了$build$函数竟然比不用还慢
真的很好写
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef unsigned long long ll;
const int N=1e5+,M=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,u,v,op,w[N];
int root;
struct Edge{
int v,ne;
}e[N<<];
int cnt,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
struct BIT{
ll c[N];
inline void add(int p,ll v){for(;p<=n;p+=(p&-p)) c[p]+=v;}
inline ll sum(int p){
ll re=;
for(;p;p-=(p&-p)) re+=c[p];
return re;
}
}C;
int block,m,pos[N];
int a[N],L[N],R[N],dfc;
int f[M][N];
void dfs(int u,int fa){
L[u]=++dfc;
a[pos[u]]++;
for(int i=;i<=m;i++) f[i][u]+=a[i]; for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa) dfs(e[i].v,u); R[u]=dfc;
a[pos[u]]--;
}
ll subtree(int x){return C.sum(R[x])-C.sum(L[x]-);}
ll sum[N];
void Change(int x,int v){
C.add(L[x],v-w[x]);
for(int i=;i<=m;i++) sum[i]+=(ll)(v-w[x])*f[i][x];
w[x]=v;
}
ll Query(int l,int r){
ll re=;
if(pos[l]==pos[r])
for(int i=l;i<=r;i++) re+=subtree(i);
else{
int _=pos[l]*block;
for(int i=l;i<=_;i++) re+=subtree(i);
for(int i=(pos[r]-)*block+;i<=r;i++) re+=subtree(i);
for(int i=pos[l]+;i<pos[r];i++) re+=sum[i];
}
return re;
}
int main(){
freopen("in","r",stdin);
n=read();Q=read();
block=sqrt(n);
m=(n-)/block+;
for(int i=;i<=n;i++) w[i]=read();
for(int i=;i<=n;i++){
u=read();v=read();
if(u) ins(u,v); else root=v;
pos[i]=(i-)/block+;
}
dfs(root,);
for(int i=;i<=n;i++) C.add(L[i],w[i]);
for(int i=;i<=m;i++){
int l=(i-)*block+,r=min(i*block,n);
for(int j=l;j<=r;j++) sum[i]+=subtree(j);
}
while(Q--){
op=read();u=read();v=read();
if(op==) Change(u,v);
else printf("%llu\n",Query(u,v));
}
}
MashiroSky怎么这么快啊.....发现他一开始子树和写在dfs里我也改成那样啦怎么还是这么慢><.......
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef unsigned long long ll;
const int N=1e5+,M=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,u,v,op,w[N];
int root;
struct Edge{
int v,ne;
}e[N<<];
int cnt,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
struct BIT{
ll c[N];
inline void add(int p,ll v){for(;p<=n;p+=(p&-p)) c[p]+=v;}
inline ll sum(int p){
ll re=;
for(;p;p-=(p&-p)) re+=c[p];
return re;
}
}C;
int block,m,pos[N];
int a[N],L[N],R[N],dfc;
int f[M][N];
ll subtree(int x){return C.sum(R[x])-C.sum(L[x]-);}
ll sum[N];
ll dfs(int u,int fa){
L[u]=++dfc; a[pos[u]]++;
C.add(L[u],w[u]);
ll s=w[u];
for(int i=;i<=m;i++) f[i][u]+=a[i];
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa) s+=dfs(e[i].v,u);
R[u]=dfc; a[pos[u]]--;
sum[pos[u]]+=s;
return s;
}
void Change(int x,int v){
C.add(L[x],v-w[x]);
for(int i=;i<=m;i++) sum[i]+=(ll)(v-w[x])*f[i][x];
w[x]=v;
}
ll Query(int l,int r){
ll re=;
if(pos[l]==pos[r])
for(int i=l;i<=r;i++) re+=subtree(i);
else{
int _=pos[l]*block;
for(int i=l;i<=_;i++) re+=subtree(i);
for(int i=(pos[r]-)*block+;i<=r;i++) re+=subtree(i);
for(int i=pos[l]+;i<pos[r];i++) re+=sum[i];
}
return re;
}
int main(){
freopen("in","r",stdin);
n=read();Q=read();
block=;
m=(n-)/block+;
for(int i=;i<=n;i++) w[i]=read();
for(int i=;i<=n;i++){
u=read();v=read();
if(u) ins(u,v); else root=v;
pos[i]=(i-)/block+;
}
dfs(root,);
while(Q--){
op=read();u=read();v=read();
if(op==) Change(u,v);
else printf("%llu\n",Query(u,v));
}
}
BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]的更多相关文章
- BZOJ 4765: 普通计算姬 (分块+树状数组)
传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...
- bzoj 4765 普通计算姬(树状数组 + 分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...
- [BZOJ4765]普通计算姬(分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1725 Solved: 376[Submit][Status][Discus ...
- [bzoj4765]普通计算姬(分块+树状数组+DFS序)
题意 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 ...
- BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- BZOJ 4765 普通计算姬 (分块 + BIT)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1547 Solved: 329[Submit][Status][Discus ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)
题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...
随机推荐
- HDU--1164
Eddy's research I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- 修改mysql密码的四种方法
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...
- HttpClient 用于解决测试时候乱码的问题
@Test public void doPostWithParam() throws Exception, IOException { CloseableHttpClient httpClient = ...
- [学习OpenCV攻略][007][缩小图片]
cvPryDown(输入图片,输出图片) 根据输出图片的大小,把输入图片进行压缩 cvPryUp(输入图片,输出图片) 根据输出图片的大小,把输入图片进行放大 #include "cv.h& ...
- memcached内存模型
内存管理 内存结构 把内存划分成不同的slab class仓库 把仓库切分成不同尺寸的小块(chunk),用来存储缓存数据 数据内存分配 首先根据数据的大小找到对应的slab class 找到空闲的c ...
- 基于TI CC2650的IPv6 over BLE(BLEach) demo
虽然BLE 5.0协议理论上已经开始支持IPv6了,但是目前市面上还没有可用的实现IPv6通信的BLE产品. 最近在网上看到一个开源的基于contiki系统,在CC2650上实现的IPv6 over ...
- -pie can only be used when targeting iOS 4.2 or later错误解决
在工程的build setting里,把IPHONEOS_DEPLOYMENT_TARGET改成4.2或以上就行了
- 读懂 Deployment YAML - 每天5分钟玩转 Docker 容器技术(125)
既然要用 YAML 配置文件部署应用,现在就很有必要了解一下 Deployment 的配置格式,其他 Controller(比如 DaemonSet)非常类似. 还是以 nginx-deploymen ...
- vue学习笔记(一)——why Vue
- protobuf java基础
1:定义proto文件: 以一个地址薄为例,从建立一个.proto文件开始,为需要序列化的数据接口加入一个message属性,在message里面,为每一个字段指定名称和类型(算是IDL吧),如下 ...