Problem Population Size
题目大意
给一个长度为n的序列,由 -1 和正整数组成,-1表示任意的正整数。
将序列分成若干段,使得任意段都是等差数列,求最少段数。
解题分析
可以发现对于某一段序列,越长越好。贪心加点,保证每段都是最长就可以了。
Tips:一段相同的数也可以算是等差数列。
参考程序
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std; #define N 200008
#define M 50008
#define LL long long
#define lson l,m,rt<<1
#define rson m,r+1,rt<<1|1
#define clr(x,v) memset(x,v,sizeof(x));
const int mo = ;
const int inf = 0x3f3f3f3f;
const int INF = ;
/**************************************************************************/
int n;
int a[N],r[N]; int main(){
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
int x=n+;
for (int i=n;i>=;i--){
r[i]=x;
if (~a[i]) x=i;
} int i=,j,k,d,num1,num2,ans=; while (i<=n){
//printf("%d\n",i );
if (a[i]==-){
j=r[i]; k=r[j];
if (j==n+) { ans++; break; } else num1=j-i;
num2=k-j;
if (k==n+){
/*if (min(num1,num2)>=a[j]) { ans+=2; break; }
else { ans++; break; }
*/
ans++; break;
}
else{
int flag=;
if ( (a[k]-a[j]) % (k-j)==){
d=(a[k]-a[j]) / (k-j);
if ( 1ll*a[j] - 1ll*d * (j-i) > ) flag =;
}
if (flag){
long long x=a[k];
for (i=k+;i<=n;i++){
x+=d;
if (x<=) break;
if (a[i]!=- && a[i]!=x) break;
}
ans++;
}
else{
/*if (min(num1,num2)>=a[j]) i=j+a[j]; else i=k;*/
ans++; i=k;
}
}
}
else
{
j=r[i];
if (j==n+) { ans++; break; } else num1=j-i-; int flag=;
if ( (a[j]-a[i]) % (j-i)==){
d=(a[j]-a[i]) / (j-i);
flag =;
}
if (flag){
long long x=a[j];
for (i=j+;i<=n;i++){
x+=d;
if (x<=) break;
if (a[i]!=- && a[i]!=x) break;
}
ans++;
}
else{
i=j;
ans++;
}
}
}
printf("%d\n",ans);
}