Codeforces 1207F Remainder Problem
阿新 • • 發佈:2020-10-25
\(\mathcal{Solution}\)
其實根號分治就可以,這個人傻乎乎地寫的樹狀陣列。
\(sum_{i,j,k}\) 為模 \(i\) 為 \(j\) 的答案字首和的樹狀陣列。
可以有兩種方法來處理詢問和修改:
-
樹狀陣列。
-
暴力一個一個跳。
因為有的 \(x\) 很大的時候暴力跳的次數很少,複雜度是對的,所以要設定一個分界線,在分界線下的用樹狀陣列,在分界線上的暴力。
設這個分界線為 \(M\),對於樹狀陣列修改一次的複雜度為 \(\mathcal{O}(M\log n )\),暴力依次跳的複雜度為 \(\mathcal{O}(\frac{n}{M})\),總複雜度就是 \(\mathcal{O}(nM\log n +\frac{n^2}{M})\)
\(\mathcal{Code}\)
其實二維陣列記錄就可以,沒有必要樹狀陣列,僅提供一個思路,程式碼參考。
#include<iostream> #include<cstdio> #define re register #define ll long long inline int read() { re int r = 0; re bool w = 0; re char ch = getchar(); while(ch < '0' || ch > '9') w = ch == '-' ? 1 : w, ch = getchar(); while(ch >= '0' && ch <= '9') r = (r << 3) + (r << 1) + (ch ^ 48), ch = getchar(); return w ? ~r + 1 : r; } inline int lowbit(int x) { return x & (-x); } inline int Max(int x, int y) { return x > y ? x : y; } inline int Min(int x, int y) { return x < y ? x : y; } const int M = 10; const int N = 500010; ll sum[M + 1][M + 1][N]; int n, optt[N], xx[N], yy[N], a[N]; //sum[i][j][k] 模i為j的前k個的字首和的tree void modify(int i, int j, int k, int val) { while(k <= n) { sum[i][j][k] += val; k += lowbit(k); } } ll query(int i, int j, int k) { re ll sumq = 0; while(k) { sumq += sum[i][j][k]; k -= lowbit(k); } return sumq; } int main() { int q = read(); for(int i = 1; i <= q; ++i) optt[i] = read(), xx[i] = read(), yy[i] = read(), n = Max(n, xx[i]); re int opt, x, y; for(int Q = 1; Q <= q; ++Q) { opt = optt[Q], x = xx[Q], y = yy[Q]; if(opt == 1) { a[x] += y; for(int i = 1; i <= M; ++i) { modify(i, x % i, x / i + (x % i > 0), y); } } else { re ll sumq = 0; if(x >= M + 1) { for(int i = y; i <= n; i += x) sumq += a[i]; } else { sumq = query(x, y, n); } printf("%lld\n", sumq); } } return 0; }