思路:先处理出山峰的数目,然后据此枚举要分的段数时间复杂度可以将为O(N)
int sum[N],a[N];
bool book[N];
void solve(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
// 枚举可能存在的每段点数.
// 每段最少为 3个点,才可能存在山峰
int ans = 0;
for(int i=n;i>=3;i--){
if(n%i==0){
int p = 1;
int cnt = 0;
int flag = 1;
for(int j=i;j<=n;j+=i){
int x = 0;
for(int k=p+1;k<j;k++){
if(a[k]>a[k-1]&&a[k]>a[k+1])
x++;
}
if(x>=1) cnt++;
else{
flag = 0;
break;
}
p = j;
}
if(!flag) continue;
ans = max(ans,n/i);
}
}
cout << ans << endl;
}
int main()
{
//buff;
int t = 1;
// scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
/*
12
1 5 3 4 3 4 1 2 3 4 6 2
12
1 5 3 4 3 2 4 2 3 4 6 2
*/
优化:找出规律:1. 从小到大枚举,i越小,n/i就越大。2. 可以前缀和预处理出每段内的山峰数.当每一段的山峰都有山峰的时候,即成立
int sum[N],a[N];
bool book[N];
void solve(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=2;i<n;i++){
if(a[i]>a[i-1] && a[i]>a[i+1]) book[i] = 1;
}
for(int i=1;i<=n;i++){
sum[i] = sum[i-1] + book[i]; // 前缀和山峰数
}
// 枚举可能存在的每段点数.
// 每段最少为 3个点,才可能存在山峰
int ans = 0;
for(int i=3;i<=n;i++){
if(n%i==0){
int p = 1;
int cnt = 0;
int flag = 1;
for(int j=i;j<=n;j+=i){
int x = sum[j] - sum[p];
if(x>=1) cnt++;
p = j;
}
if(cnt>=n/i){
ans = n/i;
break;
}
}
}
cout << ans << endl;
}
int main()
{
//buff;
int t = 1;
// scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
/*
12
1 5 3 4 3 4 1 2 3 4 6 2
12
1 5 3 4 3 2 4 2 3 4 6 2
*/