4630 no pain no game 树状数组

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4630

题意:给你N个数,然后给你M个询问,每个询问包含一个l 一个r,问你lr 这个区间中任意两个数最大的公约数。

思路:以为是l,r所以,只跟l后面的有关,所以把询问排序,数组a[]从后往前枚举约数,标记下这个约数最早出现的位置,如果这个约数出现了,那就让这个数更新一下最大的保存在树状数组中,如果没出现,那么就标记一下位置就好~这样的后面的答案会影响前面的但是前面的不会影响后面的。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <vector>
  7 #include <queue>
  8 #define loop(s,i,n) for(i = s;i < n;i++)
  9 #define cl(a,b) memset(a,b,sizeof(a))
 10 #define lowbit(x) x&-x
 11 using namespace std;
 12 struct node
 13 {
 14     int l,r,num;
 15 }q[50050];
 16  int n;
 17 int cmp(const struct node a,const struct node b)
 18 {
 19     return a.l > b.l;
 20 }
 21 
 22 int a[50050];
 23 int pre[50050];
 24 int c[50050];
 25 
 26 void update(int x,int d)
 27 {
 28     while(x <= n)
 29     {
 30         c[x] = max(c[x],d);
 31         x += lowbit(x);
 32     }
 33 }
 34 
 35 int getres(int x)
 36 {
 37     int res = 0;
 38     while(x > 0)
 39     {
 40         res  = max(c[x],res);
 41         x -= lowbit(x);
 42     }
 43 
 44     return res;
 45 
 46 }
 47 int ans[50050];
 48 int main()
 49 {
 50     int t;
 51 
 52    
 53     while (~scanf("%d",&t))
 54     {
 55 
 56         while(t--)
 57         {
 58             int cnt = 0;
 59             scanf("%d",&n);
 60             int i,j;
 61             loop(1,i,n+1)
 62             scanf("%d",&a[i]);
 63 
 64             int m;
 65             scanf("%d",&m);
 66 
 67             loop(0,i,m)
 68             {
 69                 scanf("%d %d",&q[i].l,&q[i].r);
 70                 q[i].num = i;
 71             }
 72 
 73             sort(q,q+m,cmp);
 74 
 75             cl(c,0);
 76             cl(pre,-1);
 77 
 78             for(i = n;i > 0; i--)
 79             {
 80                 for(j = 1;j*j <= a[i];j++)
 81                 {
 82                     if(a[i]%j == 0)
 83                     {
 84                         if(pre[j] != -1)
 85                             update(pre[j],j);
 86 
 87                         pre[j] = i;
 88 
 89                         if(j != (a[i]/j))
 90                         {
 91                             if(pre[a[i]/j] != -1)
 92                             update(pre[a[i]/j],a[i]/j);
 93                             pre[a[i]/j] = i;
 94                         }
 95                    }
 96                 }
 97                 while(cnt < m && q[cnt].l == i)
 98                 {
 99                     ans[q[cnt].num] = getres(q[cnt].r);
100                     cnt++;
101                 }
102             }
103 
104             loop(0,i,m)
105             printf("%d\n",ans[i]);
106         }
107     }
108     return 0;
109 }
View Code

 

posted @ 2013-08-04 14:40  某某。  阅读(151)  评论(0编辑  收藏  举报