题目连接: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 ",ans[i]); 106 } 107 } 108 return 0; 109 }