博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj4765: 普通计算姬 (分块 && BIT)
阅读量:4968 次
发布时间:2019-06-12

本文共 3183 字,大约阅读时间需要 10 分钟。

最近一直在刷分块啊

似乎感觉分块和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) 的

下面是代码

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 #define isdigit(x) (x >= '0' && x <= '9') 7 #define lowbit(x) (x & (-x)) 8 typedef unsigned long long ll; 9 const int N = 1e5 + 10; 10 const int M = 350; 11 12 int n, root, cnt, sz, tot; 13 int d[N], b[N], f[M][N], ct[N], L[N], p[N]; 14 ll s[N], c[N]; 15 vector < int > E[N]; 16 17 inline void read(int &ans) { 18 ans = 0; 19 register int res = 1; 20 static char buf = getchar(); 21 for (; !isdigit(buf); buf = getchar()) 22 if (buf == '-') res = -1; 23 for (; isdigit(buf); buf = getchar()) 24 ans = ans * 10 + buf - '0'; 25 ans *= res; 26 } 27 28 inline void addEdge(int u ,int v) { 29 E[u].push_back(v); 30 E[v].push_back(u); 31 } 32 33 inline void add(int x, ll v) { 34 while (x <= n) { 35 c[x] += v; 36 x += lowbit(x); 37 } 38 } 39 40 inline ll query(int x) { 41 ll ans = 0; 42 while (x > 0) { 43 ans += c[x]; 44 x -= lowbit(x); 45 } 46 return ans; 47 } 48 49 ll dfs(int x, int fa) { 50 ll sum = d[x]; p[x] = ++tot; 51 ct[b[x]]++; add(tot, d[x]); 52 for (int i = 1; i <= cnt; i++) f[i][x] += ct[i]; 53 for (int i = 0; i < E[x].size(); i++) { 54 int u = E[x][i]; 55 if (u == fa) continue; 56 sum += dfs(u, x); 57 } 58 ct[b[x]]--; L[x] = tot; 59 s[b[x]] += sum; 60 return sum; 61 } 62 63 inline void modify(int u, int v) { 64 add(p[u], v - d[u]); 65 for (int i = 1; i <= cnt; i++) 66 s[i] += (v - d[u]) * 1ll * f[i][u]; 67 d[u] = v; 68 } 69 70 inline ll query(int l ,int r) { 71 ll ans = 0; 72 if (b[l] == b[r]) { 73 for (int i = l; i <= r; i++) 74 ans += query(L[i]) - query(p[i] - 1); 75 return ans; 76 } 77 for (int i = b[l] + 1; i < b[r]; i++) 78 ans += s[i]; 79 for (int i = l; i <= b[l] * sz; i++) 80 ans += query(L[i]) - query(p[i] - 1); 81 for (int i = (b[r] - 1) * sz + 1; i <= r; i++) 82 ans += query(L[i]) - query(p[i] - 1); 83 return ans; 84 } 85 86 int main() { 87 int m; 88 read(n); read(m); 89 sz = sqrt(n); 90 for (int i = 1; i <= n; i++) { 91 read(d[i]); 92 b[i] = (i - 1) / sz + 1; 93 } 94 cnt = b[n]; 95 for (int i = 1; i <= n; i++) { 96 int u, v; 97 read(u); read(v); 98 if (!u) root = v; 99 else addEdge(u, v); 100 }101 dfs(root, 0);102 while (m--) {103 int op, u, v;104 read(op); read(u); read(v);105 if (op == 1)106 modify(u, v);107 else108 printf("%llu\n", query(u, v));109 }110 return 0;111 }

 

转载于:https://www.cnblogs.com/cminus/p/8571202.html

你可能感兴趣的文章
232. Implement Queue using Stacks,225. Implement Stack using Queues
查看>>
Android实战——第三方服务之Bmob后端云的答题系统小项目(四)
查看>>
读书有感----做一个踏实的程序员
查看>>
模块和包
查看>>
Spring+SpringMvc+Mybatis 框架的搭建(二)
查看>>
Pre-defined Keyboard Shortcuts (zz.IS2120@BG57IV3.T717662197)
查看>>
路由器与交换机的区别与联系
查看>>
hdu 1787 GCD Again
查看>>
Linux内核升级
查看>>
西交利物浦大学Java PAPER CODE: CSE105/12-13/S1/Resit Coursework
查看>>
简单的排序算法入门学习
查看>>
linux curl命令
查看>>
每日scrum(五)
查看>>
数据库——MySQL——存储引擎
查看>>
BZOJ4435 : [Cerc2015]Juice Junctions
查看>>
echarts实现中国地图数据展示
查看>>
2、Spring Boot 2.x 快速入门
查看>>
axios设置application/x-www-form-urlencoded
查看>>
NetworkManager——Linux强大的网络管理工具
查看>>
两天快速开发一个自己的微信小程序
查看>>