标签:
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