hdu 5381 The sum of gcd(线段树)

The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1056    Accepted Submission(s): 465


Problem Description
You have an array  A,the length of  A is  n
Let  f(l,r)=ri=lrj=igcd(ai,ai+1....aj)
 

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers  n
Second line has  n integers  Ai
Third line has one integers  Q,the number of questions
Next there are Q lines,each line has two integers  l, r
1T3
1n,Q104
1ai109
1l<rn
 

Output
For each question,you need to print  f(l,r)
 

Sample Input
 
  
2 5 1 2 3 4 5 3 1 3 2 3 1 4 4 4 2 6 9 3 1 3 2 4 2 3
 

Sample Output
 
  
9 6 16 18 23 10
 

Author
SXYZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define ls t<<1
#define rs (t<<1)|1
const int maxn = 1e4 + 200;
int val[maxn],n, m;
struct node
{
    int lg[32], rg[32], ln[32], rn[32], cntl, cntr;
    long long sum;
}tree[maxn<<2],ans;
int gcd(int a, int b)
{
    if (b == 0)return a;
    return gcd(b, a%b);
}
node Union(node a, node b)
{
    node ret;
    ret.sum = a.sum + b.sum;
    for (int i = 0; i < a.cntr; i++)
        for (int j = 0; j < b.cntl; j++)
            ret.sum += 1ll * gcd(a.rg[i], b.lg[j])*a.rn[i] * b.ln[j];
    for (int i = 0; i < a.cntl; i++)
    {
        ret.lg[i] = a.lg[i];
        ret.ln[i] = a.ln[i];
    }
    for (int i = 0; i < b.cntr; i++)
    {
        ret.rg[i] = b.rg[i];
        ret.rn[i] = b.rn[i];
    }
    int d = b.rg[b.cntr - 1], pos = b.cntr;
    for (int i = 0; i < a.cntr; i++)
    {
        int tmp = gcd(d, a.rg[i]);
        if (tmp == ret.rg[pos - 1])ret.rn[pos - 1] += a.rn[i];
        else
        {
            ret.rg[pos] = tmp;
            ret.rn[pos++] = a.rn[i];
        }
    }
    ret.cntr = pos;
    d = a.lg[a.cntl - 1], pos = a.cntl;
    for (int i = 0; i < b.cntl; i++)
    {
        int tmp = gcd(d, b.lg[i]);
        if (tmp == ret.lg[pos - 1])ret.ln[pos - 1] += b.ln[i];
        else {
            ret.lg[pos] = tmp;
            ret.ln[pos++] = b.ln[i];
        }
    }
    ret.cntl = pos;
    return ret;
}
void build(int l, int r, int t)
{
    if (l == r)
    {
        tree[t].cntl = tree[t].cntr = 1;
        tree[t].sum = tree[t].rg[0] = tree[t].lg[0] = val[l];
        tree[t].ln[0] = tree[t].rn[0] = 1;
        return;
    }
    build(l, (l + r) / 2, ls);
    build((l + r) / 2 + 1, r, rs);
    tree[t] = Union(tree[ls], tree[rs]);
}
void query(int l, int r,int lt,int rt, int t)
{
    if (lt<=l&&rt>=r)
    {
        if (lt==l)ans = tree[t];
        else ans=Union(ans, tree[t]);
        return;
    }
    int mid = (l+r) / 2;
    if (lt <= mid)query(l,mid,lt,rt, ls);
    if (rt > mid)query(mid+1,r,lt,rt, rs);
}
int main()
{
    int t,l,r;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &val[i]);
        build(1, n, 1);
        scanf("%d", &m);
        while (m--)
        {
            scanf("%d%d", &l, &r);
            query(1,n,l,r,1);
            printf("%I64d\n", ans.sum);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_22522375/article/details/51524802