题意: 一共n个数, 每个-1都可以变成一个正数, 现在要求最少数目的等差子序列,并且在这个子序列必须要连着截取一段,不能分开截取。 样例1: 8 6 4 2 1 4 7 10 2 可以分成 { 8 6 4 2} {1 4 7 10 } {2} 3个等差子序列。
题解: 每一个序列都尽可能有更多的个数,贪心的去取就好了。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int N = 2e5+5; 5 ll n; 6 ll a[N]; 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 while(cin >> n) 13 { 14 for(int i = 1; i <= n; i++) 15 cin >> a[i]; 16 a[n+1] = -2; 17 bool star = 1, ok = 0; 18 ll cnt = 0, d = 0, ans = 0; 19 for(int i = 1; i <= n; i++) 20 { 21 if(a[i] == -1 && !ok && star) 22 cnt++; 23 else if(a[i] == -1 && ok) 24 { 25 if(a[i-1] + d > 0) a[i] = a[i-1] + d;//如果前面有等差序列 26 else ans++, cnt = 1, star = 1, ok = 0;//那么就将这个-1放进去 27 } 28 else if(a[i] == -1 && !star) 29 { 30 int j = i+1; 31 while(a[j] == -1) j++; 32 if(a[j] == -2) 33 break; 34 ll dis = j+1-i; 35 ll diff = a[j] - a[i-1]; 36 if(diff % dis == 0)// a[i-1]!=-1 a[j]!=-1 且有差等 37 { //那么a[i]-a[j-1]内的-1都可以被代替成合法数 38 ok = 1; 39 d = diff / dis; 40 i = j; 41 } 42 else ok = 0, star = 1, i = j-1, ans++; 43 } 44 else if(a[i] != -1 && cnt) 45 { 46 int j = i+1; 47 while(a[j] == -1) j++; 48 if(a[j] == -2) break; 49 ll dis = j-i; 50 ll diff = a[j]-a[i]; 51 if(diff % dis == 0) 52 { 53 d = diff / dis; 54 if(a[i]-d*cnt > 0) ok = 1, star = 0, i = j; 55 else i = j-1, ok = 0, star = 1, ans++; 56 } 57 else i = j-1, ok = 0, star = 1, ans++; 58 cnt = 0; 59 } 60 else if(star) 61 star = 0; 62 else if(!ok) 63 d = a[i] - a[i-1], ok = 1; 64 else if(a[i-1]+d != a[i]) 65 ans++, star = 1, ok = 0, i--; 66 } 67 cout << ans + 1 << endl;//最后答案要加一,因为最后至少有一个序列 68 } 69 return 0; 70 }