bzoj4765: 普通计算姬 (分块 && BIT)
最近一直在刷分块啊
似乎感觉分块和BIT是超级棒的搭档啊
这道题首先用dfs预处理一下
得到每一个sum值
此时查询是O(1)的 (前缀和乱搞什么的
但是修改需要O(n) (需要修改该节点所有祖先的sum
复杂度就爆了呀
此时考虑分块优化
似乎弹飞绵羊也是这样思考得出分块做法的
首先分成 √n 块
sum[i]记录第i块的sum和
中间的块直接用sum数组处理 两边用树状数组暴力求
这样查询就是O(√n)的 (其实有一些常数的... 就当是 √n 好了)
修改的话在dfs时用f[i][j]表示第j个点对于第i块的贡献 (需要算几次什么的
然后直接修改块就好了 复杂度也是O (√n) 的
下面是代码
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define isdigit(x) (x >= '0' && x <= '9')
#define lowbit(x) (x & (-x))
typedef unsigned long long ll;
const int N = 1e5 + ;
const int M = ; int n, root, cnt, sz, tot;
int d[N], b[N], f[M][N], ct[N], L[N], p[N];
ll s[N], c[N];
vector < int > E[N]; inline void read(int &ans) {
ans = ;
register int res = ;
static char buf = getchar();
for (; !isdigit(buf); buf = getchar())
if (buf == '-') res = -;
for (; isdigit(buf); buf = getchar())
ans = ans * + buf - '';
ans *= res;
} inline void addEdge(int u ,int v) {
E[u].push_back(v);
E[v].push_back(u);
} inline void add(int x, ll v) {
while (x <= n) {
c[x] += v;
x += lowbit(x);
}
} inline ll query(int x) {
ll ans = ;
while (x > ) {
ans += c[x];
x -= lowbit(x);
}
return ans;
} ll dfs(int x, int fa) {
ll sum = d[x]; p[x] = ++tot;
ct[b[x]]++; add(tot, d[x]);
for (int i = ; i <= cnt; i++) f[i][x] += ct[i];
for (int i = ; i < E[x].size(); i++) {
int u = E[x][i];
if (u == fa) continue;
sum += dfs(u, x);
}
ct[b[x]]--; L[x] = tot;
s[b[x]] += sum;
return sum;
} inline void modify(int u, int v) {
add(p[u], v - d[u]);
for (int i = ; i <= cnt; i++)
s[i] += (v - d[u]) * 1ll * f[i][u];
d[u] = v;
} inline ll query(int l ,int r) {
ll ans = ;
if (b[l] == b[r]) {
for (int i = l; i <= r; i++)
ans += query(L[i]) - query(p[i] - );
return ans;
}
for (int i = b[l] + ; i < b[r]; i++)
ans += s[i];
for (int i = l; i <= b[l] * sz; i++)
ans += query(L[i]) - query(p[i] - );
for (int i = (b[r] - ) * sz + ; i <= r; i++)
ans += query(L[i]) - query(p[i] - );
return ans;
} int main() {
int m;
read(n); read(m);
sz = sqrt(n);
for (int i = ; i <= n; i++) {
read(d[i]);
b[i] = (i - ) / sz + ;
}
cnt = b[n];
for (int i = ; i <= n; i++) {
int u, v;
read(u); read(v);
if (!u) root = v;
else addEdge(u, v);
}
dfs(root, );
while (m--) {
int op, u, v;
read(op); read(u); read(v);
if (op == )
modify(u, v);
else
printf("%llu\n", query(u, v));
}
return ;
}
bzoj4765: 普通计算姬 (分块 && BIT)的更多相关文章
- [BZOJ4765]普通计算姬(分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1725 Solved: 376[Submit][Status][Discus ...
- [bzoj4765]普通计算姬——分块
Brief Description 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权 值和.支持下列两种操作: 1 给定两个整数u,v, ...
- BZOJ4765: 普通计算姬
BZOJ4765: 普通计算姬 题目描述 传送门 题目分析 求的和非常奇怪,不具有连续性,所有上树的数据结构全死了. 考虑分块,思考对于一段连续的询问区间可以直接询问整块,零散块可以在树上dfs序暴力 ...
- 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...
- [bzoj4765]普通计算姬(分块+树状数组+DFS序)
题意 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 ...
- BZOJ 4765 普通计算姬 (分块 + BIT)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1547 Solved: 329[Submit][Status][Discus ...
- BZOJ4765 普通计算姬(分块+树状数组)
对节点按编号分块.设f[i][j]为修改j号点对第i块的影响,计算f[i][]时dfs一遍即可.记录每一整块的sum.修改时对每一块直接更新sum,同时用dfs序上的树状数组维护子树和.查询时累加整块 ...
- BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...
- BZOJ 4765: 普通计算姬 (分块+树状数组)
传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...
随机推荐
- Linux网络课程学习第三天
第三天在线视频学习. 学习内容:继续详细介绍了第二章节 Linux常用命令的使用方法. 学习感受:万事开头难,作为Linux零基础的我相信在这本书学完之后会有所收获. 学习心得:记住刘老师的一句口头禅 ...
- 提取 Microsoft.ReportViewer等dll
ReportViewer 在开发环境没问题 发布以后可能会提示找不到 Microsoft.ReportViewer 下的几个dll 可以用用下面脚本在开发服务器上提取 相应的dll @SET dest ...
- php 常用数学函数
函数 描述 实例 输入 输出 abs() 求绝对值 $abs = abs(-4.2); //4.2 数字 绝对值数字 ceil() 进一法取整 echo ceil(9.999); // 10 浮点数 ...
- 小白月赛22 A : 操作序列
A:操作序列 析题得说: 考察点 : 模拟,STL库容器的使用 坑点 : 区间不要搞丢东西 难点 : 这个题比较变态的是我们不知道每次输入每行是一个数还是两个数,就需要进行判断, 怎么判断呢?用 sc ...
- Github+Hexo一站式部署个人博客(原创)
写在前面 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 本文源链接:https://www.cnblogs.com/chloneda/p/hexo.ht ...
- sql已经在视图展示的语句如何显示别的表中的内容而不改变原有的值
1.这个功能是我在公司的时候的一个需求,我师傅和我说你不可能就是说你可以添加的时候是数字但是展现给客户看的时候是数字最好是名称因为客户不知道这是什么意思 2.于是我陷入了漫长的实现这个功能中一开始只是 ...
- java - 各类OOM分析
StackOverflowError 比较常见的问题,虚拟机栈中栈帧过多超出栈容量,常见发生在递归方法深度过深. OutOfMemoryError java heap space java堆内存不足以 ...
- python:利用smtplib发送邮件详解
本文转自:https://www.cnblogs.com/insane-Mr-Li/p/9121619.html 自动化测试中,测试报告一般都需要发送给相关的人员,比较有效的一个方法是每次执行完测试用 ...
- 解决并发问题的CAS思想及原理
全称为:Compare and swap(比较与交换),用来解决多线程并发情况下使用锁造成性能开销的一种机制: 原理思想:CAS(V,A,B),V为内存地址,A为预期原值,B为新值.如果内存地 ...
- 杭电oj_2035——人见人爱A^B(java实现)
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2035 思路:(网上学来的,偏向数学的不咋懂/捂脸)每次乘法的时候都取后三位(可能有些含糊,直接看代码吧 ...