http://acm.hdu.edu.cn/showproblem.php?pid=4630
给的题解没看懂。。搜解题报告看 了N久 终于在cui大神的指点下 搞明白咋回事了
将1-N中的每个数ai的倍数的位置p求出来 它们任意两个p组成的区间内约数至少为ai 在询问的区间L-R中如果存在这样的区间pi-pj 那肯定存在相邻的 然后排好序 相邻的为一个区间l-r保存起来
以r从小到大排序 将输入的询问区间进行离线处理 以R由小到大排序 对于每个区间插入r值比R小的区间 求值时以L为下界求到N 其实就是求到R 到R还快了500多ms。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 using namespace std; 7 #define N 50005 8 #define lowbit(x) (x&(-x)) 9 int a[N],p[N],o[N],ans[N],re[N<<2],n; 10 struct node 11 { 12 int ll,r,val; 13 }tt[N*20],q[N]; 14 bool cmp(node a,node b) 15 { 16 if(a.r==b.r) 17 return a.ll<b.ll; 18 return a.r<b.r; 19 } 20 void add(int x,int va) 21 { 22 while(x>0) 23 { 24 re[x]=max(re[x],va); 25 x-=lowbit(x); 26 } 27 } 28 int getsum(int x,int y) 29 { 30 int mm=0; 31 while(x<=y) 32 { 33 mm = max(mm,re[x]); 34 x += lowbit(x); 35 } 36 return mm; 37 } 38 int main() 39 { 40 int i,j,t,m; 41 cin>>t; 42 while(t--) 43 { 44 memset(re,0,sizeof(re)); 45 cin>>n; 46 for(i = 1; i <= n ; i++) 47 { 48 scanf("%d",&a[i]); 49 p[a[i]] = i; 50 re[i] = 1; 51 } 52 int g,k=0; 53 for(i = 2 ; i <= n/2 ;i++) 54 { 55 g = 0; 56 for(j = i ; j <= n ; j+=i) 57 { 58 o[g++] = p[j]; 59 } 60 sort(o,o+g); 61 for(j = 1 ; j < g ; j++) 62 { 63 tt[k].ll = o[j-1]; 64 tt[k].r = o[j]; 65 tt[k++].val = i; 66 } 67 } 68 sort(tt,tt+k,cmp); 69 cin>>m; 70 for(i = 1; i <= m ;i++) 71 { 72 scanf("%d%d",&q[i].ll,&q[i].r); 73 q[i].val = i; 74 } 75 sort(q+1,q+m+1,cmp); 76 int oo=0; 77 78 for(i = 1; i <= m ;i++) 79 { 80 if(q[i].ll==q[i].r) 81 { 82 ans[q[i].val] = 0; 83 continue; 84 } 85 for(j = oo ; j < k&&tt[j].r<=q[i].r ; j++) 86 { 87 add(tt[j].ll,tt[j].val); 88 } 89 ans[q[i].val] = getsum(q[i].ll,q[i].r); 90 oo = j; 91 } 92 for(i = 1 ;i <= m ;i++) 93 printf("%d\n",ans[i]); 94 } 95 return 0; 96 }