1. 程式人生 > >bzoj4765: 普通計算姬 (分塊 && BIT)

bzoj4765: 普通計算姬 (分塊 && BIT)

getc pos return pac define ... sta ext getchar()

最近一直在刷分塊啊

似乎感覺分塊和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 <cstdio>
  2 #include <cmath>
  3 #include <algorithm>
  4 #include <vector>
  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 else 108 printf("%llu\n", query(u, v)); 109 } 110 return 0; 111 }

bzoj4765: 普通計算姬 (分塊 && BIT)