CSP第23次 202109-2 非零段划分 C语言90分答案
第23次csp我是有去参加的,当时 第一题100分 第二题70分 第四题10分
网上很多满分答案时间复杂度都是O(n*logn)也达标了,运行时间在300ms左右。
我下面这段代码只有O(n)的时间复杂度,仅31ms,运行速度应该是全网最快的了。
但只有90分,实在找不到哪里出错了,希望有大佬可以指点一下。
#include <stdio.h>
int arr[500010]={0};//存储题目给的数组
int dp_change[10010]={0};//动态规划,p为几时非零段数量的变化,往后看就懂了
int main()
{
int i,n,p,max_p=10000,out=0,count=0;
scanf("%d",&n);
for(i=1;i<=n;i++)//读入数组arr,并将相邻元素去重
{
scanf("%d",&arr[i]);
if(arr[i-1]==arr[i])
n--,i--;
}
for(i=1;i<=n;i++)//计算dp_change[]
{
if(arr[i]<arr[i-1]&&arr[i]<arr[i+1])//如果某个数比自身左右两边的数都小,那么当p等于自身的值+1时非零段会多一个,例如自身为1时22122
dp_change[arr[i]+1]++;
else if(arr[i]>arr[i-1]&&arr[i]>arr[i+1])//如果某个数比自身左右两边的数都大,那么当p等于自身的值+1时非零段会少一个,例如自身为1时00100
dp_change[arr[i]+1]--;
}
if(n==0)
out=count = 0;
else
out=count = ++dp_change[1];//dp_change[1]+1即p=0的非零段数量
for(p=2;p<=max_p;p++)//递推出所有p的情况
{
count+=dp_change[p];
count>out?out=count:0;
}
printf("%d",out);
return 0;
}
下面这段是70分运行超时,把这个版本也放出来吧
#include <stdio.h>
//70分,运行超时
int arr[500010];
int main()
{
int i,j,n,p,max_p=10000,out=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
for(p=0;p<=max_p;p++)
{
int need=1,count=0;
for(i=0;i<n;i++)
{
if(need&&arr[i]>=p)
{
need=0;
count++;
}else if(arr[i]<p)
need=1;
}
count>out?out=count:0;
}
printf("%d",out);
return 0;
}
下面这段是当时考csp的时候的代码,当时思维还是很不开窍的哈哈,还没开始学习算法
当时是想着通过拉大p的间距(多提交几个不同p加大间距),偷一下测试点漏洞,减少运行时间。不建议大家看下面这段了,笑一笑就好
#include <stdio.h>
//70分,运行超时
int main()
{
int i,j,k,l;
int n;
int max=0,out=0;
scanf("%d",&n);
int arr[n+1];
for(i=1;i<=n;i++)
{
scanf("%d",&arr[i]);
if(arr[i]>max)max = arr[i];
}
if(n>500)
for(k=1;k<max;k+=5)
{
int tmp[n+1];
int count=0;
for(i=1;i<=n;i++)
if(arr[i]<k)
tmp[i]=0;
else
tmp[i]=arr[i];
for(i=1;i<=n;i++)
{
if(tmp[i-1]==0||i==1)
{
for(j=i;j<=n;j++)
{
if(j==n||tmp[j+1]==0)
{
int ok=1;
for(l=i;l<=j;l++)
{
if(tmp[l]<=0)
{
ok=0;
break;
}
}
if(ok==1)
{
count++;
i=j+1;
// printf("count++\n",count);
break;
}
}
}
}
}
// printf("k=%d out=%d\n",k,out);
if(count>out)
out=count;
}
else
for(k=1;k<max;k+=2)
{
int tmp[n+1];
int count=0;
for(i=1;i<=n;i++)
if(arr[i]<k)
tmp[i]=0;
else
tmp[i]=arr[i];
for(i=1;i<=n;i++)
{
if(tmp[i-1]==0||i==1)
{
for(j=i;j<=n;j++)
{
if(j==n||tmp[j+1]==0)
{
int ok=1;
for(l=i;l<=j;l++)
{
if(tmp[l]<=0)
{
ok=0;
break;
}
}
if(ok==1)
{
count++;
i=j+1;
// printf("count++\n",count);
break;
}
}
}
}
}
// printf("k=%d out=%d\n",k,out);
if(count>out)
out=count;
}
printf("%d",out);
return 0;
}