传送门

题意:

一棵树,支持单点修改和询问以$[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. ACM_并查集

    //题意:ignatius过生日,客人来到,他想知道他需要准备多少张桌子.然而一张桌子上面只能坐上相互熟悉的人, //其中熟悉可定义成为A与B认识,B与C认识,我们就说A,B,C相互熟悉 .例如A与B ...

  2. vue安装babel依赖报错

    刚刚因为一些原因把依赖包删除,重新install了一下,结果报错 deprecate babel-preset-es2015@* ???? Thanks for using Babel: we rec ...

  3. Vue.js实现一个SPA登录页面的过程

    技术栈 vue.js 主框架 vuex 状态管理 vue-router 路由管理 一般过程 在一般的登录过程中,一种前端方案是: 检查状态:进入页面时或者路由变化时检查是否有登录状态(保存在cooki ...

  4. [国嵌笔记][019][Eclipse集成开发环境]

    Eclipse集成开发环境的作用 可以编译程序,也可以对程序进行在线调试 集成开发环境 1.JLink连接开发板的JTAG 2.JLink连接PC的USB 3.eclipse软件 4.gdb serv ...

  5. TP5.0 excel 导入导出

    引第三方的phpexcel类库放到 ThinkPHP\Library\Vendor\demo下,自己建的文件夹demo 再将Excel.class放到ThinkPHP\Library\Org\clas ...

  6. destoon标签

    http://blog.csdn.net/oYuHuaChen/article/details/54601509 ------------

  7. Java中的对象Object方法之---wait()和notifiy()

    这一篇咋们继续,接着来介绍wait()和notify()方法,我们都知道这两个方法和之前介绍的方法不太一样,那就是这两个方法是对象Object上的,不属于Thread类上的.我们也知道这两个方法是实现 ...

  8. eclipse代码编辑区字符串自动转义设置

    在做接口测试时,有时接口请求参数非常多,如果用java相关方法去拼接参数,难度较大,并且非常浪费时间,那如何快速将整个请求参数拼接成一个字符串呢?为了解决这个问题,只要简单配置下eclipse设置即可 ...

  9. C# 将Access中时间段条件查询的数据添加到ListView中

    C# 将Access中时间段条件查询的数据添加到ListView中 一.让ListView控件显示表头的方法 在窗体中添加ListView 空间,其属性中设置:View属性设置为:Detail,Col ...

  10. SNMP PDU解析

    (注:此文章仅为个人学习,研究,原创作者:Penguinbupt,原创文章网址:http://blog.csdn.net/u010566813/article/details/50490858) SN ...