【树状数组】HDU 5381 The sum of gcd
题意:f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj),q次询问。
思路:考虑每加入一个点,那么贡献了r-l+1个区间,然后会发现区间内与新加入的r这个的gcd都是一块一块的,然后树状数组维护这个即可。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long ll; template <class T> inline bool rd(T &ret) { char c; int sgn; if(c = getchar() , c == EOF) return false; while(c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return true; } const int MAX_N = 10007; struct Node { int l, r, id; bool operator < (const Node &rhs) const { return r < rhs.r; } }; int n; struct Bit { ll bit[MAX_N]; void clear() { memset(bit, 0, sizeof bit); } void add(int i, ll v) { if (i == 0) bit[0] += v; else { for (;i > 0; i -= i & -i) bit[i] += v; } } ll query(int i) { if (i < 0) return 0; else { ll re = 0; for (;i <= n; i += i & -i) re += bit[i]; return re; } } }; ll gcd(ll a, ll b) { while (a %= b ^= a ^= b ^= a); return b; } int a[MAX_N], val[MAX_N], pre[MAX_N]; ll ans[MAX_N]; Node q[MAX_N]; Bit B[2]; void update(int l, int r, ll v) { B[0].add(l - 1, v * (r - l + 1)); B[0].add(r, v * (r + 1)); B[0].add(l - 1, -v * (r + 1)); B[1].add(l - 1, -v); B[1].add(r, v); } int main() { int T; rd(T); while (T-- > 0) { rd(n); for (int i = 1; i <= n; ++i) rd(a[i]); B[0].clear(); B[1].clear(); int Q; rd(Q); for (int i = 0; i < Q; ++i) { rd(q[i].l), rd(q[i].r); q[i].id = i; } sort(q, q + Q); int k = 0; val[1] = a[1]; pre[1] = 0; update(1, 1, a[1]); for (int i = 2; i <= n; ++i) { pre[i] = i - 1, val[i] = a[i]; int j = i; while (j > 0) { val[j] = gcd(val[j], a[i]); while (pre[j] > 0 && gcd(val[pre[j]], val[j]) == val[j]) pre[j] = pre[pre[j]]; update(pre[j] + 1, j, val[j]); j = pre[j]; } while (k < Q && q[k].r == i) ans[q[k].id] = B[0].query(q[k].l) - B[1].query(q[k].l) * q[k++].l; } for (int i = 0; i < Q; ++i) printf("%I64d\n", ans[i]); } return 0; }