标签:
A
简单题
B
简单题
C
简单题
D
简单期望
E
求最小的sum(|a[i]|) 使得每连续k个a[i]之和组成的新序列单调递增
显然a[i]<a[i+k]<a[i+2*k]<a[i+3*k]
找到一段连续的?和左端点和右端点 贪心即可
#include <cstdio> #include <cstring> #include <cstdlib> typedef __int64 LL; int a[100010], b[100010], c[100010]; int n, m; bool cal(int s, int e, int k) { if(s < 1 && e > n) { int x = (e-k)/m; int y = -x/2; for(int i = k; i <= n; i += m) a[i] = y++; } else if(s >= 1 && e > n) { int x = (e-s)/m-1; int y = -x/2; if(a[s] >= -x/2) y = a[s]+1; for(int i = s+m; i <= n; i += m) a[i] = y++; } else if(s < 1 && e <= n) { int x = (e-k)/m; int y = x/2; if(a[e] <= x/2) y = a[e]-1; for(int i = e-m; i >= k; i -= m) { a[i] = y--; } } else { int x = (e-s)/m-1; LL tmp = (LL)a[e]-(LL)a[s]-1; if(tmp < x) return false; int y1 = -x/2; int y2 = x/2; if(a[s] >= -x/2) { y1 = a[s]+1; for(int i = s+m; i < e; i += m) a[i] = y1++; } else if(a[e] <= x/2) { y1 = a[e]-1; for(int i = e-m; i > s; i -= m) a[i] = y1--; } else { for(int i = s+m; i < e; i += m) a[i] = y1++; } } return true; } int main() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { char s[22]; scanf("%s", s); if(s[0] == '?') b[i] = 1; else a[i] = atoi(s); } int flag = 0; for(int i = 1; i <= m; i++) { int t = 0; for(int j = i; j <= n; j += m) { if(!b[j]) t = j; while(j <= n && b[j]) j += m; if(t < j) { if(!cal(t, j, i)) { flag = 1; break; } } if(j <= n) t = j; } for(int j = i+m; j <= n; j += m) { if(a[j] <= a[j-m]) { flag = 1; break; } } if(flag) break; } if(!flag) { for(int i = 1; i <= n; i++) printf("%d ", a[i]); puts(""); } else printf("Incorrect sequence\n"); return 0; }
Codeforces Round #293 (Div. 2)
标签:
原文地址:http://blog.csdn.net/u011686226/article/details/44115487