题目 : http://codeforces.com/problemset/problem/416/D
思路:从上一个等差数列的结尾加一处开始找两个非-1的数,算出公差。如果公差为小数或者该公差导致前面的一串-1中有可能会有数变成非正数,就将第一个非-1的数和前面的一堆-1和两数间的一堆-1作为第一个数列,再以第二个非-1的数开头找等差数列。否则就再向后找可以合并到这个等差数列的数加入这个数列,找不到了就从这个等差数列的结尾加一处再找等差数列。
最开始我想不出来,然后看了提示,按照提示写了。过了样例后提交了17次,然后再79个点死活过不去了。
主要是犯了这些错误:
1、开头、结尾是-1时处理不当
2、公差为小数时没有考虑
3、应该用long long 型存储
……
然后看了别人的程序,思路差不多,写的有些不同。我原来的程序是对每个数判断看能否加入前一个等差数列,而那个程序是按上面的思路写的,对于前面的-1变得小于等于0的情况处理的也好一些。我又写了一遍,然后就过了。
#include<stdio.h>
#include<iostream>
using namespace std;
long long n;
long long a[200005]= {0};
long long sum=0;
int main() {
scanf("%I64d",&n);
for(long long i=1; i<=n; i++) {
scanf("%I64d",&a[i]);
}
long long i=1;
while(i<=n) {
sum++;
long long firstnum=0,nextnum=0;
for(long long j=i; j<=n; j++) {
if(a[j]>=0) {
if(firstnum==0) {
firstnum=j;
} else {
nextnum=j;
break;
}
}
}
if(nextnum==0) {
break;
}
if((a[nextnum]-a[firstnum])%(nextnum-firstnum)!=0) {
i=nextnum;
continue;
}
long long d=(a[nextnum]-a[firstnum])/(nextnum-firstnum);
if(a[nextnum]-(nextnum-i)*d<=0) {
i=nextnum;
continue;
}
long long x=a[nextnum];
for(i=nextnum+1; i<=n; i++) {
if(x+d<=0) {
break;
}
if(a[i]==-1||a[i]==x+d) {
x+=d;
} else {
break;
}
}
}
printf("%I64d",sum);
return 0;
}