bzoj4765 普通计算姬
Posted MashiroSky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4765 普通计算姬相关的知识,希望对你有一定的参考价值。
题意
给出一棵有根树,$n$个点每个都有一个点权。$m$组操作每次可以修改一个点权或者询问编号在区间$[l,r]$的点的子树权值和的和。
Solution
我们对节点编号分块,每一块统计该块中的节点的子树权值和的和。dfs处理出修改一个节点,需要对应修改它的祖先和它的所在的哪些块。另外再开一个树状数组,树状数组中每一个元素是对应dfs的点的权值,这样我们可以求出任意子树的权值和。
对于询问,在中间的块直接统计。两侧零散的块在树状数组上暴力查询子树权值和。所以令块的大小$S=\sqrt{n/\log{n}}$,复杂度$O(n\sqrt{n\log{n}})$
细节
会爆long long
代码
// bzoj4765 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define ULL unsigned long long #define inf (1ll<<30) #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) using namespace std; const int maxn=100010; int head[maxn],L[maxn],R[maxn],t[maxn][350],pos[maxn],n,m,S,bn,cnt,dfn,Dargen; LL c[maxn],d[maxn],a[maxn]; ULL s[maxn]; struct edge {int to,next;}e[maxn<<1]; int lowbit(int x) { return x&-x; } void add(int x,LL val) { for (int i=x;i<=n;i+=lowbit(i)) c[i]+=val; } LL query(int x) { LL res=0; for (int i=x;i;i-=lowbit(i)) res+=c[i]; return res; } void link(int u,int v) { e[++cnt]=(edge){v,head[u]};head[u]=cnt; e[++cnt]=(edge){u,head[v]};head[v]=cnt; } LL dfs(int x,int fa) { L[x]=++dfn;d[pos[x]]++; LL sum=a[x];add(L[x],a[x]); for (int i=1;i<=bn;i++) t[x][i]=d[i]; for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) sum+=dfs(e[i].to,x); R[x]=dfn;d[pos[x]]--;s[pos[x]]+=sum; return sum; } int main() { scanf("%d%d",&n,&m); S=300;bn=n/S+(n%S!=0); for (int i=1;i<=n;i++) pos[i]=(i-1)/S+1; for (int i=1;i<=n;i++) scanf("%lld",&a[i]); for (int u,v,i=1;i<=n;i++) { scanf("%d%d",&u,&v); if ((LL)u*v==0) Dargen=u+v; else link(u,v); } dfs(Dargen,0); for (int op,x,y,i=1;i<=m;i++) { scanf("%d%d%d",&op,&x,&y); if (op==1) { LL d=y-a[x];a[x]=y; for (int j=1;j<=bn;j++) s[j]+=d*t[x][j]; add(L[x],d); } if (op==2) { ULL ans=0; if (pos[x]==pos[y]) for (int j=x;j<=y;j++) ans+=query(R[j])-query(L[j]-1); else { for (int j=pos[x]+1;j<pos[y];j++) ans+=s[j]; for (int j=x;j<=S*pos[x];j++) ans+=query(R[j])-query(L[j]-1); for (int j=(pos[y]-1)*S+1;j<=y;j++) ans+=query(R[j])-query(L[j]-1); } printf("%llu\n",ans); } } return 0; }
以上是关于bzoj4765 普通计算姬的主要内容,如果未能解决你的问题,请参考以下文章