HDU 5726 GCD(ラインツリーGCD、良いタイトル)

题目链接
A1、...、(0 <ai≤1000,000,000):あなたはNのシーケンス(N≤100,000)整数を与えます。Q(Q≤100,000)クエリがあります。各クエリリットルの場合は、(1≤l<r≤N)ようにGCD(アル"あなたは計算GCD(アル、アル+ 1、...、AR)を持っており、ペア(L '、R')の数をカウントrを、ら'+ 1、...、Ar'は)等しいGCD(AL、ら+ 1、...、AR)。

入力
入力の最初の行は、あなたが解決する必要があるテストケースの数を表して数Tを、含まれています。

それぞれの場合の最初の行は、整数の数を示す、番号Nを含有します。

2行目はNの整数、A1、...、(0 <ai≤1000,000,000)を含みます。

第三のラインは、クエリの数を表す、数値Qを含んでいます。

次のQラインの場合は、i番目の行は2つの番号、李用のスタンド、Riは、i番目のクエリに立つ含まれています。

出力
各ケースに対しては、あなたが出力する必要があります。:先頭に「ケース#T」(引用符で、tはテストケースの数を意味し、1から始まります)。

各クエリについて、次の行に出力するように2つの数値を必要とします。最初の番号は、(AL、ら+ 1、...、AR)GCDを表し、2番目の数字は対(L '、R')の数を表すようにGCD(AL '、アル' + 1、...、Ar 'は)同じGCD(AL、ら+ 1、...、AR)。

サンプル入力
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4

サンプル出力
ケース#1:
1 8
2 4
2 4
6 1

著者の
HIT

ソース
2016マルチ大学研修コンテストザ・1つの
アイデア:私たちは木のラインを見つけることができ間隔GCDが、それを要求するか、同じ数の?列挙が可能であるので、我々は、サブインターバルN内の長GCDの数がよりログより確実でないことを知っているときに列挙[I] [前に1、[それを横断するときI- 1] GCDデマンド型とカウント数、クエリがO(1)であってもよいです。例えば、[I-1]〜1既にGCDのxは、今GCD(X、[I])は、Y次に、yに等しく、[CNT] +のGCDに固有の番号(X)に等しいです。番号、それをマッピングするマップと、その後GCD預金。

#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]);
        }
    }
}
公開された150元の記事 ウォンの賞賛0 ビュー5532

おすすめ

転載: blog.csdn.net/qq_42479630/article/details/104591020