18110 Koishi's travel, Satori's travel

18110 Koishi's travel, Satori's travel

该题有题解

时间限制:4000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: 不限定

 

Description

    Koishi travel for a long time. 
    No one knows where she will go include herself because of her unconscious action.
    She may be losting in the lost forest.
    She may be fishing on the misty lake .
    She may be playing in the Hakurei jinja.
    She may be now behind you...

    Satori is worried about her younger sister, Koishi. Wanted to find Koishi, She embarked on a journey.
    Because of the ability to read minds, She know where Koishi is seen by reading other people's mind 
if they had seen her.

    She finds one after another place, one after another location.
    Through her efforts, now she knows that Koishi has been to n places and she was in the (ai)th place when time is i.
    She knows a lot about her sister. So She guess the next place she will go is the maximum of ai % aj where i < j.
    If the result is 0. Satori will very happy because Koishi will go back home.

    But there are too many place. Satori can't calculate the result quickly.
    If not calculate the result as soon as possible, Koishi maybe go to the next place.
    Now Satori need your help. Can you help Satori to calculate the result?

 




输入格式

    The input file begins with a line of integer T (T <= 100) indicating the number of test case.
    Each test case contains two lines. The first line contains an integer n (2 <= n <= 50000). Then 
the second line contains n positive integers in the array A, separated by spaces. No Ai will exceed n.
The sum of n will not exceed 500000.



输出格式

    For each test case, print the answer in one line.



 

输入样例

2
5
1 2 3 4 5
5
5 4 3 2 1



 

输出样例

4
2



 

提示

sample1: 4 % 5 is the maximum
sample2: 5 % 3 is the maximum



 

作者

 201330330101

 

 

   题意:给你n个数,找出最大值的ai%aj(i<j)。

   首先,题目里有一个很重要的条件:n最大为50000且数列中的n个数都不会大于n; 那么,就应该从这里作为突破口,寻找高效的算法。 然后再来看:对于每一个数aj,前面的元素取余它时,可能的结果只有0~aj-1; 所以我们就可以从左往右扫一遍数列,对于每一个元素aj,我们一段一段的考虑:即0~aj-1,aj+1~2*aj-1,....直至大于n就停止;在每一段中时要进行的操作就是判断前面的数列中是否存在在这个段中的元素,然后更新最大值(这里就用线段树来解决)。  这样一来,每个数要判断的次数就为n/aj,而判断的复杂度是logn。      

       另外,可以在开一个数组来标记重复出现的数字的最后出现的下标;因为重复出现的数字只要考虑最后一个,它覆盖到前面的元素是最多的,所以直接算最后一个可以节约重复计算的时间。        (整体的复杂度不清楚到底是多少。。。不过下面的AC代码是跑的2000ms多一些 =_=)

   

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <utility>
10 #include <map>  //GL&HF
11 #include <set>
12 typedef long long ll;
13 const int inf=0x3f3f3f3f;
14 const int mod=(1e9)+7;
15 const int MAXN=5e4+10;
16 using namespace std;
17 
18 int a[MAXN],last[MAXN],bit[MAXN*3+10];
19 
20 void build(int l,int r,int id)    //建立线段树, id为树中结点的下标
21 {
22     bit[id]=0;
23     if(l==r) return;
24     int mid=(l+r)>>1;
25     build(l,mid,id<<1);
26     build(mid+1,r,id<<1|1);
27 }
28 void push(int id)         //更行区间结点id的值
29 {
30     bit[id]=max(bit[id<<1],bit[id<<1|1]);
31 }
32 void update(int value,int l,int r,int id)
33 {
34     if(l==r)
35     {
36         bit[id]=value;
37         return;
38     }
39     int mid=(l+r)>>1;
40     if(value<=mid) update(value,l,mid,id<<1);
41     else update(value,mid+1,r,id<<1|1);
42     push(id);
43 }
44 int query(int ql,int qr,int l,int r,int id)   //查询操作
45 {
46     if(ql<=l&&r<=qr) return bit[id];
47     //
48     int mid=(l+r)>>1,res=0;
49     if(ql<=mid) res=max(res,query(ql,qr,l,mid,id<<1));
50     if(qr>mid) res=max(res,query(ql,qr,mid+1,r,id<<1|1));
51     return res;
52 }
53 
54 int main()
55 {
56     //freopen("input.txt","r",stdin);
57     int t,n;
58     scanf("%d",&t);
59     while(t--)
60     {
61         scanf("%d",&n);
62         for(int i=1;i<=n;i++) scanf("%d",&a[i]),last[a[i]]=i;
63         build(0,n,1);
64         //
65         int ans=-inf;
66         for(int i=1;i<=n;i++)
67         {
68             if(last[a[i]]==i)
69             {
70                 int l=0,r;
71                 while(l<=n)
72                 {
73                     r=min(n,l+a[i]-1);
74                     int temp=query(l,r,0,n,1);
75                     //
76                     ans=max(ans,temp%a[i]);
77                     l+=a[i];
78                 }
79             }
80             update(a[i],0,n,1);
81         }
82         //
83         printf("%d\n",ans);
84     }
85     return 0;
86 }

 

posted @ 2016-10-13 20:09  爱喝可乐的咖啡  阅读(422)  评论(0编辑  收藏  举报