bzoj 4765: 普通计算姬 分块
来源:互联网 发布:怎样退出淘宝账号 编辑:程序博客网 时间:2024/04/30 02:01
题意
给定一棵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数组分块,那么我们可以先用差分预处理出s[i,j]表示第i块中dfs序的第j个数的系数,ans[i]表示第i块的答案。那么修改就可以在
对于dfs序,我们可以用树状数组来维护,那么修改的复杂度就是
据说这样是可以卡过去的。
但我们有更优的办法。
注意到修改的复杂度远远低于查询的复杂度,那么我们考虑是否能够均衡这两个操作的复杂度呢?答案是肯定的。
我们可以对dfs序进行分块,处理的是前缀和,那么修改操作就变成了
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>using namespace std;typedef unsigned long long LL;const int N=100005;const int B=420;int n,m,cnt,last[N],pos[N],tim,mn[N],mx[N],sum[B][N],bel[N],block,sta[B],end[B],root,t[N];struct edge{int to,next;}e[N*2];LL ans[B],dfn[N],tag[B],a[N];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void addedge(int u,int v){ e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void dfs(int x,int fa){ mn[x]=++tim;pos[tim]=x; for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa) continue; dfs(e[i].to,x); } mx[x]=tim;}void prework(){ dfs(root,0); for (int i=1;i<=n;i++) dfn[i]=dfn[i-1]+a[pos[i]]; for (int i=1;i<=bel[n];i++) { memset(t,0,sizeof(t)); for (int j=sta[i];j<=end[i];j++) t[mn[j]]++,t[mx[j]+1]--; for (int j=1;j<=n;j++) sum[i][j]=sum[i][j-1]+t[j],ans[i]+=(LL)sum[i][j]*a[pos[j]]; }}void modify(int x,LL y){ LL delta=y-a[x];a[x]=y; for (int i=1;i<=bel[n];i++) ans[i]+=(LL)delta*sum[i][mn[x]]; for (int i=bel[mn[x]]+1;i<=bel[n];i++) tag[i]+=delta; for (int i=mn[x];i<=end[bel[mn[x]]];i++) dfn[i]+=delta;}LL find(int l,int r){ return dfn[r]+tag[bel[r]]-dfn[l-1]-tag[bel[l-1]];}LL query(int l,int r){ LL tot=0; if (bel[l]==bel[r]) { for (int i=l;i<=r;i++) tot+=find(mn[i],mx[i]); return tot; } for (int i=bel[l]+1;i<bel[r];i++) tot+=ans[i]; for (int i=l;i<=end[bel[l]];i++) tot+=find(mn[i],mx[i]); for (int i=sta[bel[r]];i<=r;i++) tot+=find(mn[i],mx[i]); return tot;}int main(){ n=read();m=read(); block=sqrt(n); for (int i=1;i<=n;i++) { a[i]=read(); bel[i]=(i+block-1)/block; if (!sta[bel[i]]) sta[bel[i]]=i; end[bel[i]]=i; } for (int i=1;i<=n;i++) { int x=read(),y=read(); if (!x) root=y; else addedge(x,y); } prework(); while (m--) { int op=read(),x=read();LL y=read(); if (op==1) modify(x,y); else printf("%llu\n",query(x,y)); } return 0;}
0 0
- [分块] BZOJ 4765 普通计算姬
- bzoj 4765: 普通计算姬 分块
- BZOJ 4765 普通计算姬(分块表+树状数组)
- BZOJ 4765: 普通计算姬 分块+树状数组
- bzoj 4765: 普通计算姬(分块+树状数组)
- bzoj 4765: 普通计算姬(分块 dfs序)
- bzoj 4765: 普通计算姬
- [BZOJ Contest-2017省队十连测推广赛1·T1][BZOJ4765][分块][dfs序]普通计算姬
- 4765: 普通计算姬
- BZOJ 1257: [CQOI2007]余数之和sum 分块计算,基础数论
- 分块计算
- bzoj 2453 && bzoj 2120 分块
- BZOJ 2141 排队 分块
- bzoj 3343(分块)
- bzoj 2453(分块)
- 【bzoj 2821】 作诗 分块
- bzoj 2141: 排队 分块
- BZOJ 2002 分块
- The Tomcat installation directory is not valid. It is missing...
- Cefsharp.Wpf 打包
- [JZOJ5094]鸽子
- 64位jdk编译的项目 在32位jdk上运行不正常!
- 漏洞库网站
- bzoj 4765: 普通计算姬 分块
- opencv 判断矩阵相等
- 1095: [ZJOI2007]Hide 捉迷藏
- Android 置Activity全屏和无标题
- vsftpd服务
- wechall php系列之No Escape
- 123456
- -----hdu 4811 ball
- struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Action的实现类