hdu 4630 线段树+在线操作

hdu 4630

算是一道好题目吧,不断地求一段区间的最大公约数,‘|’表示有x这个约数,‘o’表示没有,

|ooo|oo|那么我们可以根据最后一个‘|’的位置来进行在线查询,将要查询的区间按右边界进行排序,更新‘|’的前一个位置。用线段树。。。。。。

//hdu 4630 线段树
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <stdio.h>
#include <bitset>
#include <queue>
#define maxn 50002
using namespace std;
int num[maxn],pos[maxn],n,m,p[maxn];
vector<int> g[maxn+5];
struct e1
{
    int x,y,id,ans;
}que[maxn];
struct e2
{
    int l,r,ma;
}tree[maxn*6];

bool cmp(e1 a,e1 b)
{
    if(a.y==b.y)
        return a.x<b.x;
    return a.y<b.y;
}

void pushup(int a)
{
    tree[a].ma=max(tree[a*2+1].ma,tree[a*2].ma);
}

void build(int a,int l,int r)
{
    tree[a].l=l;
    tree[a].r=r;
    tree[a].ma=0;
    if(l==r)
        return;
    int mid=(l+r)/2;
    build(a*2,l,mid);
    build(a*2+1,mid+1,r);
}

void insert(int a,int p,int v)
{
    if(tree[a].l==tree[a].r)
    {
        tree[a].ma=max(tree[a].ma,v);
        return;
    }
    int mid=(tree[a].l+tree[a].r)/2;
    if(p<=mid)
        insert(a*2,p,v);
    else
        insert(a*2+1,p,v);
    pushup(a);
}

int query(int a,int l,int r)
{
    if(l<=tree[a].l&&tree[a].r<=r)
        return tree[a].ma;
    int mid=(tree[a].l+tree[a].r)/2;
    int ans=0;
    if(l<=mid)
        ans=max(query(a*2,l,r),ans);
    if(mid<r)
        ans=max(query(a*2+1,l,r),ans);
    return ans;
}

int main()
{
    int T,j,k;
    for(j=1;j<=maxn;j++)
        for(k=j;k<=maxn;k+=j)
          g[k].push_back(j);
    //freopen("d:\\in.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
      int i,ii,cnt=0;
      memset(pos,0,sizeof(pos));
      scanf("%d",&n);
      for(i=1;i<=n;i++)
        scanf("%d",&num[i]);
      scanf("%d",&m);
      for(i=0;i<m;i++)
      {
        scanf("%d %d",&que[i].x,&que[i].y);
        que[i].id=i;
      }
      sort(que,que+m,cmp);
      build(1,0,n);
      for(i=1;i<=n;i++)
      {
         int u=num[i];
         for(ii=0;ii<g[u].size();ii++)
         {
             insert(1,pos[g[u][ii]],g[u][ii]);
             pos[g[u][ii]]=i;
         }
         while(cnt<m&&que[cnt].y==i)
         {
              p[que[cnt].id]=query(1,que[cnt].x,que[cnt].y);
              cnt++;
         }
      }
      for(i=0;i<m;i++)
        printf("%d\n",p[i]);
    }
    return 0;
}

你可能感兴趣的:(hdu 4630 线段树+在线操作)