HDU 5381The sum of gcd 莫队算法

来源:互联网 发布:网络研修收获与反思 编辑:程序博客网 时间:2024/05/20 20:22

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5381

题意:给定一个数组,每次询问给出l和r,求出 

思路:看的大牛的代码,心累

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#define debug() puts("here")using namespace std;typedef long long ll;const int N = 10010;struct node{    int l, r, id;} g[N];int n, m, unit;ll res[N], tmp;int a[N], b[N], c[N];struct vv{    int id, g;};vector<vv> vec1[N], vec2[N];int gcd(int a, int b){    return !b ? a : gcd(b, a % b);}bool cmp(node a, node b){    return a.l/unit != b.l/unit ? a.l/unit < b.l/unit : a.r < b.r;}void work(){    for(int i = 1; i <= n; i++) vec1[i].clear(), vec2[i].clear();    for(int i = 1; i <= n; i++)    {        if(i == 1) vec1[i].push_back(vv{i, a[i]});        else        {            int curg = a[i], id = i;            for(auto &it : vec1[i-1])            {                int g = gcd(curg, it.g);                if(g != curg) vec1[i].push_back(vv{id, curg});                curg = g, id = it.id;            }            vec1[i].push_back(vv{id, curg});        }    }    for(int i = n; i >= 1; i--)    {        if(i == n) vec2[i].push_back(vv{i, a[i]});        else        {            int curg = a[i], id = i;            for(auto &it : vec2[i+1])            {                int g = gcd(curg, it.g);                if(g != curg) vec2[i].push_back(vv{id, curg});                curg = g, id = it.id;            }            vec2[i].push_back(vv{id, curg});        }    }}ll calr(int l, int r){    ll sum = 0;    int tr = r;    for(auto &it : vec1[r])        if(it.id >= l)        {            sum += (ll)(tr - it.id + 1) * it.g;            tr = it.id - 1;        }        else        {            sum += (ll)(tr - l + 1) * it.g;            break;        }    return sum;}ll call(int l, int r){    ll sum = 0;    int tl = l;    for(auto &it : vec2[l])        if(it.id <= r)        {            sum += (ll)(it.id - tl + 1) * it.g;            tl = it.id + 1;        }        else        {            sum += (ll)(r - tl + 1) * it.g;            break;        }    return sum;}void solve(){    unit = (int)sqrt(1.0 * n);    sort(g+1, g+1+m, cmp);    int l = 1, r = 0;    tmp = 0;    for(int i = 1; i <= m; i++)    {        while(r < g[i].r) tmp += calr(l, ++r);        while(r > g[i].r) tmp -= calr(l, r--);        while(l < g[i].l) tmp -= call(l++, r);        while(l > g[i].l) tmp += call(--l, r);        res[g[i].id] = tmp;    }    for(int i = 1; i <= m; i++) printf("%lld\n", res[i]);}int main(){    int t;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);        scanf("%d", &m);        for(int i = 1; i <= m; i++) scanf("%d%d", &g[i].l, &g[i].r), g[i].id = i;        work();        solve();    }    return 0;}


0 0