看的别人的题解,离线之后,按r排序,枚举1-n,利用pre[j],存上次j的倍数出现的位置,树状数组里统计的当前位置到最后的最大值,树状数组是求区间最值其实应该很麻烦的,但是此题用法只是求到最后的最大值,插入的时候,往前更新就好了,类似求和。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 int num[50100]; 6 int p[50100]; 7 int n; 8 struct node 9 { 10 int l,r,id; 11 } que[50001]; 12 bool cmp(node a,node b) 13 { 14 return a.r < b.r; 15 } 16 bool cmp1(node a,node b) 17 { 18 return a.id < b.id; 19 } 20 int pre[50101]; 21 int ans[50101]; 22 int lowbit(int t) 23 { 24 return t&(-t); 25 } 26 void insert(int t,int d) 27 { 28 while(t) 29 { 30 p[t] = max(p[t],d); 31 t -= lowbit(t); 32 } 33 } 34 int getmax(int t) 35 { 36 int maxz = 0; 37 while(t <= n) 38 { 39 maxz = max(maxz,p[t]); 40 t += lowbit(t); 41 } 42 return maxz; 43 } 44 int main() 45 { 46 int i,j,t,m,tnum; 47 scanf("%d",&t); 48 while(t--) 49 { 50 memset(p,0,sizeof(p)); 51 memset(pre,0,sizeof(pre)); 52 scanf("%d",&n); 53 for(i = 1; i <= n; i ++) 54 scanf("%d",&num[i]); 55 scanf("%d",&m); 56 for(i = 0; i < m; i ++) 57 { 58 scanf("%d%d",&que[i].l,&que[i].r); 59 que[i].id = i; 60 } 61 sort(que,que+m,cmp); 62 tnum = 0; 63 for(i = 1; i <= n; i ++) 64 { 65 if(tnum == m) break; 66 for(j = 1; j*j <= num[i]; j ++) 67 { 68 if(num[i]%j == 0) 69 { 70 if(pre[j] != 0) 71 insert(pre[j],j); 72 pre[j] = i; 73 if (j * j== num[i]) continue ; 74 if(pre[num[i]/j] != 0) 75 insert(pre[num[i]/j],num[i]/j); 76 pre[num[i]/j] = i; 77 } 78 } 79 while(tnum < m&&que[tnum].r == i) 80 { 81 ans[que[tnum].id] = getmax(que[tnum].l); 82 tnum ++; 83 } 84 } 85 sort(que,que+m,cmp1); 86 for(i = 0;i < m;i ++) 87 { 88 if(que[i].l == que[i].r) 89 printf("0 "); 90 else 91 printf("%d ",ans[i]); 92 } 93 } 94 return 0; 95 }