HDU4630-No Pain No Game(离线,线段树)

Problem Description

Life is a game,and you lose it,so you suicide.
But you can not kill yourself before you solve this problem:
Given you a sequence of number a1, a2, ..., an.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l, r],what is the maximum gcd(a, b)? If there's no way to choose two distinct number(l=r) then the answer is zero.

Input

First line contains a number T(T <= 5),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1 <= n <= 50000).
The second line contains n number a1, a2, ..., an.
The third line contains a number Q(1 <= Q <= 50000) denoting the number of queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n),denote a query.
 

Output

For each test cases,for each query print the answer in one line.
 

Sample Input

1
10
8 2 4 9 5 7 10 6 1 3
5
2 10
2 4
6 9
1 4
7 10

Sample Output

5 2 2 4 3

题目大意:

给一个序列,然后q次询问[l,r]询问两两gcd最大值是多少(不能是同一个数),无解输出0;

解题思路:

想总结一下,感觉自己好菜啊。

两两取gcd,最后的值肯定是该数的约数。

也就是说,数是可以一个一个加入的。

现将约数分解。

一个数被加入。如果他的约数k上一次在p处,那么询问左端点<=p的话答案就至少值为k。

就离线处理一下。

保证加入的点来更新答案。

我觉得和HH的项链有点像。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll spc<<1
  5 #define rrr spc<<1|1
  6 using std::max;
  7 struct qst{
  8     int l,r;
  9     int no;
 10     int ans;
 11     void Insert(int i)
 12     {
 13         no=i;
 14         ans=0;
 15         scanf("%d%d",&l,&r);
 16         return ;
 17     }
 18 }q[1000000];
 19 int maxs[1000000];
 20 int a[1000005];
 21 int lst[1000005];
 22 int n,Q;
 23 int T;
 24 bool cmp(qst x,qst y)
 25 {
 26     return x.r<y.r;
 27 }
 28 bool cmq(qst x,qst y)
 29 {
 30     return x.no<y.no;
 31 }
 32 void Reset(void)
 33 {
 34     memset(lst,0,sizeof(lst));
 35     memset(maxs,0,sizeof(maxs));
 36     return ;
 37 }
 38 void pushup(int spc)
 39 {
 40     maxs[spc]=max(maxs[lll],maxs[rrr]);
 41     return ;
 42 }
 43 void update(int spc,int l,int r,int v,int pos)
 44 {
 45     if(l==r)
 46     {
 47         maxs[spc]=max(v,maxs[spc]);
 48         return ;
 49     }
 50     int mid=(l+r)>>1;
 51     if(pos<=mid)
 52         update(lll,l,mid,v,pos);
 53     else
 54         update(rrr,mid+1,r,v,pos);
 55     pushup(spc);
 56     return ;
 57 }
 58 int query(int l,int r,int ll,int rr,int spc)
 59 {
 60     if(l>rr||ll>r)
 61         return -0x3f3f3f3f;
 62     if(ll<=l&&r<=rr)
 63         return maxs[spc];
 64     int mid=(l+r)>>1;
 65     return max(query(l,mid,ll,rr,lll),query(mid+1,r,ll,rr,rrr));
 66 }
 67 int main()
 68 {
 69     scanf("%d",&T);
 70     while(T--)
 71     {
 72         Reset();
 73         scanf("%d",&n);
 74         for(int i=1;i<=n;i++)
 75             scanf("%d",&a[i]);
 76         scanf("%d",&Q);
 77         for(int i=1;i<=Q;i++)
 78             q[i].Insert(i);
 79         std::sort(q+1,q+Q+1,cmp);
 80         int j=1;
 81         for(int i=1;i<=n;i++)
 82         {
 83             for(int k=1;k*k<=a[i];k++)
 84             {
 85                 if(a[i]%k==0&&lst[k])
 86                     update(1,1,n,k,lst[k]);
 87                 if(a[i]%k==0&&lst[a[i]/k]&&k!=a[i]/k)
 88                     update(1,1,n,a[i]/k,lst[a[i]/k]);
 89                 if(a[i]%k==0)
 90                     lst[k]=lst[a[i]/k]=i;
 91             }
 92             while(q[j].r==i)
 93             {
 94                 if(j>Q)
 95                     break;
 96                 if(q[j].l>=q[j].r)
 97                     q[j].ans=0;
 98                 else
 99                     q[j].ans=query(1,n,q[j].l,q[j].r,1);
100                 j++;
101             }
102         }
103         std::sort(q+1,q+Q+1,cmq);
104         for(int i=1;i<=Q;i++)
105             printf("%d
",q[i].ans);
106     }
107     return 0;
108 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/9768573.html