传送门

题意:

一棵树,支持单点修改和询问以$[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序]的更多相关文章

  1. BZOJ 4765: 普通计算姬 (分块+树状数组)

    传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...

  2. bzoj 4765 普通计算姬(树状数组 + 分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...

  3. [BZOJ4765]普通计算姬(分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1725  Solved: 376[Submit][Status][Discus ...

  4. [bzoj4765]普通计算姬(分块+树状数组+DFS序)

    题意 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 ...

  5. BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...

  6. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  7. BZOJ 4765 普通计算姬 (分块 + BIT)

    4765: 普通计算姬 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1547  Solved: 329[Submit][Status][Discus ...

  8. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  9. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

随机推荐

  1. 什么是命名空间?php命名空间的基本应用分享

    什么是命名空间? php中声明的函数名.类名和常量的名称,在同一次运行中是不能重复的,否则会产生一个致命的错误,常见的解决方法是约定一个前缀.例如 ,在项目开发时,用户 User 模块中的控制器和数据 ...

  2. Spark算子--coalesce和repartition

    coalesce和repartition--Transformation类算子 代码示例

  3. c++---天梯赛---大笨钟

    ★题目: ★思路分析: 对可能的情况进行分类处理.在这里我把它们分成了3大类. ①不在敲钟时间 ②在敲钟时间但为整点 ③在敲钟时间且不为整点. 在敲钟时间段内我们可分别对晚8点前后进行分类讨论, 我们 ...

  4. 猜随机数(控制台输入,字符串转int)

    package com.hanqi.suijishu; import java .util.Random; // main方法类 专门用来运行方法 public class Main { public ...

  5. Oracle:FOR循环语句练习

    --打印输出从1到10的正整数DECLARE v_i NUMBER(10) := 0;BEGIN LOOP v_i := v_i + 1; DBMS_OUTPUT.put_line(v_i); EXI ...

  6. 分享给有需要的你,精选了10套web开发免费视频教程~~

    在这里给大家精选百度传课里的一些比较好的视频教程,比较适合新手们,有需要的可以收藏着学习!!  蓝鸥微信小程序全方位深度解析 链接:http://www.chuanke.com/v4702151-19 ...

  7. 地图API地址  百度地图开放平台

    http://lbsyun.baidu.com/index.php?title=jspopular

  8. 在js中怎样获得checkbox里选中的多个值?

    https://zhidao.baidu.com/question/203897221.html 思路:利用name属性值获取checkbox对象,然后循环判断checked属性(true表示被选中, ...

  9. android 基础02 - Activity 的生命周期及状态

    返回栈 Android 中的 Activity 是可以层叠的,当我们启动一个新的 Activity 时,就会覆盖在原有的 Activity 之上, 点击 Back 会销毁当前 Activity,下面的 ...

  10. plist涉及到沙盒的一个问题

    http://blog.csdn.net/wowxavi1/article/details/8557271