ZJNU 2220 - array

找最长的等差数列长度

数据范围是 n<=2000,a[i]<=2000

容易想到的是枚举等差数列前两项,得到差值后向后查找

a数组存数值,b数组存某个数出现的个数(也可判断是否出现过)

这是个O(n^3)级别的想法,所以必须在此基础上继续优化

首先排除公差为0的情况,即找出相同的数出现最多次的次数

然后将数列排序后去重,使得剩下的元素两两不相等

这时候就可以开始枚举 i 和 j 两项了

但是从最坏情况考虑,2000项互不相同的测试点时间复杂度仍然是O(n^3),去重没法对这种情况进行优化

所以可以从剪枝入手,在每一次搜索前将可能得到的最大的答案跟目前的答案进行比较

即先把a数组最大的元素存在变量mx中,枚举出 a[i] 后根据 (mx-a[i])/d 来计算可能得到的最大的答案

扫描二维码关注公众号,回复: 9577672 查看本文章

如果这个值小于等于目前的答案ans,说明这个分支无法对答案做出贡献,就可以直接跳出整个 j 循环

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[2050],b[4050];
 4 void solve(){
 5     int n,i,j,k,d,ans=1,mx=0;
 6     memset(b,0,sizeof b);
 7     cin>>n;
 8     for(i=1;i<=n;i++){
 9         cin>>a[i];
10         ans=max(ans,++b[a[i]]);
11         mx=max(mx,a[i]);
12     }
13     sort(a+1,a+1+n);
14     n=unique(a+1,a+1+n)-a-1;
15     for(i=1;i<n;i++)
16         for(j=i+1;j<=n;j++){
17             d=a[j]-a[i];
18             if((mx-a[i])/d<=ans)
19                 break;
20             for(k=a[j]+d;b[k];k+=d);
21             ans=max(ans,(k-a[i])/d);
22         }
23     cout<<ans<<'\n';
24 }
25 int main(){
26     ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
27     int T;cin>>T;for(int t=1;t<=T;t++)
28         solve();
29     return 0;
30 }

猜你喜欢

转载自www.cnblogs.com/stelayuri/p/12409846.html