hdu 4630 查询[L,R]区间内任意两个数的最大公约数

No Pain No Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2000    Accepted Submission(s): 851

Problem Description
Life is a game,and you lose it,so you suicide.
But you can not kill yourself before you solve this problem:
Given you a sequence of number a1, a2, ..., an.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l, r],what is the maximum gcd(a, b)? If there's no way to choose two distinct number(l=r) then the answer is zero.
 
Input
First line contains a number T(T <= 5),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1 <= n <= 50000).
The second line contains n number a1, a2, ..., an.
The third line contains a number Q(1 <= Q <= 50000) denoting the number of queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n),denote a query.
 
Output
For each test cases,for each query print the answer in one line.

Sample Input

1
10
8 2 4 9 5 7 10 6 1 3
5
2 10
2 4
6 9
1 4
7 10


Sample Output

5
2
2
4
3
/*
hdu 4630 查询[L,R]区间内任意两个数的最大公约数

给你n个数,m个询问,输出区间[l,r]内的任意两个数的最大公约数

对于每一个数而言,对左右都会造成影响,所以我们考虑把查询按r从小到大排序,遇到r则输出结果
像这样的话我们就能只考虑a[i]与 [1,i-1]之间数的关系
因为是求的最大公约数,所以枚举a[i]的因子,如果发现此因子已经出现过,则在此前因子出现的地方赋值
(因为我们是求[l,r]之间的,并不能保证之前因子出现的位置在此之内),然后更新该因子的位置

hhh-2016-04-05 19:55:32
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <vector>
#include <functional>
#define lson (i<<1)
#define rson ((i<<1)|1)
using namespace std;
const int maxn = 5e5+5;
int pos[maxn];
int a[maxn];
int tans[maxn];
struct node
{
    int l,r;
    int Max;
    int mid()
    {
        return (l+r)>>1;
    }
} tree[maxn<<2];

void push_up(int i)
{
    tree[i].Max = max(tree[lson].Max,tree[rson].Max);
}

void build(int i,int l,int r)
{
    tree[i].l = l,tree[i].r = r;
    tree[i].Max=0;
    if(l == r)
        return ;
    int mid = tree[i].mid();
    build(lson,l,mid);
    build(rson,mid+1,r);
    push_up(i);
}

void update(int i,int k,int val)
{
    if(tree[i].l == tree[i].r && tree[i].l == k)
    {
        tree[i].Max =  max(tree[i].Max,val);
        return ;
    }
    int mid = tree[i].mid();
    if(k <= mid)
        update(lson,k,val);
    else
        update(rson,k,val);
    push_up(i);
}

int query(int i,int l,int r)
{
    if(tree[i].l >= l && tree[i].r <= r)
    {
        return tree[i].Max;
    }
    int ans = 0;
    int mid = tree[i].mid();
    if(l <= mid)
        ans = max(ans,query(lson,l,r));
    if(r > mid)
        ans = max(ans,query(rson,l,r));
    return ans;
}

struct qy
{
    int l,r;
    int id;
} qry[maxn];

bool cmp(qy a ,qy b)
{
    return a.r < b.r;
}

int main()
{
    int T;
    int n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        build(1,1,n);
        memset(pos,-1,sizeof(pos));
        for(int i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        int m;
        scanf("%d",&m);
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d",&qry[i].l,&qry[i].r);
            qry[i].id = i;
        }
        sort(qry+1,qry+1+m,cmp);

        for(int i = 1,cur = 1; i <= n; i++)
        {

            for(int j = 1; j*j <= a[i]; j++)
            {
                if(a[i]%j == 0)
                {
                    if(pos[j] != -1)
                        update(1,pos[j],j);
                    if(pos[a[i]/j]!= -1)
                        update(1,pos[a[i]/j],a[i]/j);
                    pos[j] = i;
                    pos[a[i]/j] = i;
                }
            }

            while(i == qry[cur].r && cur <= m)
            {
                tans[qry[cur].id] = query(1,qry[cur].l,qry[cur].r);
                cur ++;
            }
        }
        for(int i = 1; i <= m; i++)
        {
            printf("%d
",tans[i]);
        }
    }
    return 0;
}

  



原文地址:https://www.cnblogs.com/Przz/p/5409559.html