Fork me on GitHub

HDU 4630 No Pain No Game 树状数组+离线操作

题意:给一串数字,每次查询[L,R]中两个数的gcd的最大值。

解法:容易知道,要使取两个数让gcd最大,这两个数最好是倍数关系,所以处理出每个数的所有倍数,两两间根据倍数关系形成一条线段,值为该数。那么每次查询[L,R]之间两数gcd的最大值即为查询[L,R]中值最大的线段,离线所有的查询数据,然后按右端点坐标从小到大排序,依次往右加入即可。

这里学到了树状数组维护最大值的写法。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 50007

int c[N];
struct node
{
    int l,r,v;
}a[10*N],Q[N];
int n,pos[N],num[N],ans[N];

int cmp(node ka,node kb) { return ka.r < kb.r; }
int lowbit(int x) { return x&-x; }

void modify(int x,int val)
{
    while(x > 0)
    {
        c[x] = max(c[x],val);
        x -= lowbit(x);
    }
}

int getmax(int x)
{
    int res = 0;
    while(x <= n)
    {
        res = max(res,c[x]);
        x += lowbit(x);
    }
    return res;
}

int main()
{
    int t,i,j,x,q,tot;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            pos[x] = i;
            c[i] = 1;
        }
        tot = 0;
        for(i=2;i<=n/2;i++)
        {
            int k = 0;
            for(j=i;j<=n;j+=i)  //i的倍数
                num[k++] = pos[j];
            sort(num,num+k);
            for(j=1;j<k;j++)
            {
                 a[tot].l = num[j-1];
                 a[tot].r = num[j];
                 a[tot++].v = i;
            }
        }
        scanf("%d",&q);
        for(i=0;i<q;i++)
        {
            scanf("%d%d",&Q[i].l,&Q[i].r);
            Q[i].v = i;
        }
        sort(a,a+tot,cmp);
        sort(Q,Q+q,cmp);
        j = 0;
        for(i=0;i<q;i++)
        {
            if(Q[i].l == Q[i].r)
            {
                ans[Q[i].v] = 0;
                continue;
            }
            while(j < tot && a[j].r <= Q[i].r)
                modify(a[j].l,a[j].v),j++;
            ans[Q[i].v] = getmax(Q[i].l);
        }
        for(i=0;i<q;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
View Code

 

posted @ 2014-09-23 18:48  whatbeg  阅读(261)  评论(0编辑  收藏  举报