hdu 5726 GCD (line tree gcd, good title)

题目链接
Give you a sequence of N(N≤100,000) integers : a1,…,an(0<ai≤1000,000,000). There are Q(Q≤100,000) queries. For each query l,r you have to calculate gcd(al,al+1,…,ar) and count the number of pairs(l′,r′)(1≤l<r≤N)such that gcd(al′,al′+1,…,ar′) equal gcd(al,al+1,…,ar).

Input
The first line of input contains a number T, which stands for the number of test cases you need to solve.

The first line of each case contains a number N, denoting the number of integers.

The second line contains N integers, a1,…,an(0<ai≤1000,000,000).

The third line contains a number Q, denoting the number of queries.

For the next Q lines, i-th line contains two number , stand for the li,ri, stand for the i-th queries.

Output
For each case, you need to output “Case #:t” at the beginning.(with quotes, t means the number of the test case, begin from 1).

For each query, you need to output the two numbers in a line. The first number stands for gcd(al,al+1,…,ar) and the second number stands for the number of pairs(l′,r′) such that gcd(al′,al′+1,…,ar′) equal gcd(al,al+1,…,ar).

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

Sample Output
Case #1:
1 8
2 4
2 4
6 1

Author
HIT

Source
2016 Multi-University Training Contest The 1
idea: interval gcd we can find tree line, but the same number of how demand it? We know that a number of length gcd within the sub-interval n is certainly not more than a log, because the enumeration is possible when the enumeration to a [i] when traversing it before [1, a [i- 1]] gcd demand type and the number of counts, the query can be O (1). For example, a 1 to the [i-1] is already a gcd x, so now gcd (x, a [i]) is equal to y, then y [cnt] is equal to the number of inherent in the + gcd (x) the number, then gcd deposit with map mapping it.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+1;
ll a[maxn];
ll gcd (ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
struct node{
    int l,r;
    ll num;
}tree[maxn<<2];
map<ll,ll>p1,p2,cnt;
void build(int l,int r,int x)
{
    tree[x].l=l,tree[x].r=r;
    if(l==r){
        tree[x].num=a[l];return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,x<<1);
    build(mid+1,r,x<<1|1);
    tree[x].num=gcd(tree[x<<1].num,tree[x<<1|1].num);
}
ll query(int x,int l,int r)
{
    if(l==tree[x].l&&tree[x].r==r) return tree[x].num;
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid) return query(x<<1,l,r);
    else if(l>mid) return query(x<<1|1,l,r);
    else return gcd(query(x<<1,l,mid),query(x<<1|1,mid+1,r));
}
int main()
{
    int T,n,m,l,r;
    scanf("%d",&T);
    for(int j=1;j<=T;++j)
    {
        printf("Case #%d:\n",j);
        scanf("%d",&n);
        p1.clear(),p2.clear(),cnt.clear();
        for(int i=1;i<=n;++i)  
        {
            scanf("%lld",&a[i]);
            cnt[a[i]]++;
            p2[a[i]]++;
            for(auto it=p1.begin();it!=p1.end();it++)
            {
                ll t=gcd(a[i],it->first);
                cnt[t]+=it->second;
                p2[t]+=it->second;
            }
            p1.clear();
            for(auto it=p2.begin();it!=p2.end();it++) p1[it->first]=it->second;
            p2.clear();
        }
        build(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&l,&r);
            ll ans=query(1,l,r);
            printf("%lld %lld\n",ans,cnt[ans]);
        }
    }
}
Published 150 original articles · won praise 0 · Views 5532

Guess you like

Origin blog.csdn.net/qq_42479630/article/details/104591020
gcd