Codeforces Round #293 (Div. 2) -- E. Arthur and Questions (思路 + 贪心)

E. Arthur and Questions
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

After bracket sequences Arthur took up number theory. He has got a new favorite sequence of length n (a1, a2, ..., an), consisting of integers and integer k, not exceeding n.

This sequence had the following property: if you write out the sums of all its segments consisting of k consecutive elements (a1  +  a2 ...  +  ak,  a2  +  a3  +  ...  +  ak + 1,  ...,  an - k + 1  +  an - k + 2  +  ...  +  an), then those numbers will form strictly increasing sequence.

For example, for the following sample: n = 5,  k = 3,  a = (1,  2,  4,  5,  6) the sequence of numbers will look as follows: (1  +  2  +  4,  2  +  4  +  5,  4  +  5  +  6) = (7,  11,  15), that means that sequence a meets the described property.

Obviously the sequence of sums will have n - k + 1 elements.

Somebody (we won't say who) replaced some numbers in Arthur's sequence by question marks (if this number is replaced, it is replaced by exactly one question mark). We need to restore the sequence so that it meets the required property and also minimize the sum |ai|, where |ai| is the absolute value of ai.

Input

The first line contains two integers n and k (1 ≤ k ≤ n ≤ 105), showing how many numbers are in Arthur's sequence and the lengths of segments respectively.

The next line contains n space-separated elements ai (1 ≤ i ≤ n).

If ai  =  ?, then the i-th element of Arthur's sequence was replaced by a question mark.

Otherwise, ai ( - 109 ≤ ai ≤ 109) is the i-th element of Arthur's sequence.

Output

If Arthur is wrong at some point and there is no sequence that could fit the given information, print a single string "Incorrect sequence" (without the quotes).

Otherwise, print n integers — Arthur's favorite sequence. If there are multiple such sequences, print the sequence with the minimum sum |ai|, where |ai| is the absolute value of ai. If there are still several such sequences, you are allowed to print any of them. Print the elements of the sequence without leading zeroes.

Examples
Input
3 2
? 1 2
Output
0 1 2 
Input
5 1
-10 -9 ? -7 -6
Output
-10 -9 -8 -7 -6 
Input
5 3
4 6 7 2 9
Output
Incorrect sequence
大体题意:

给你n 和k ,给你n 个数a1,a2,a3,,,,an(其中包括一些未知数)
使得(a1+a2+,,,+ak),(a2+a3+,,,+ak+1),(a3+a4+,,,ak+2)这n-k+1个数是严格递增的!
最后输出这n 个数,使得这n个数的绝对值之和最小!。
思路:
逐一做差便可发现:
a1 < ak+1 < a2k+1 <...
a2 < ak+2 < 2k+2 <...
..
..
根据这个公式进行枚举!
在初始化时:
问号初始化为INF,其余的用atoi 函数直接把字符串转到了十进制数字!
那个公式前后两项位置都差了个k,所以要补一补边界,n+1 -- n+k全都补为INF + 1(注意不能是INF!)
然后开始枚举每一项a1,a2,,ak,总共k项。
在每一项中prev 代表第一个问号之前,a[j]已经遍历到了最后一个问号之后的确定数字。其中要统计出连续问号
出现了几次 sum。
那么a[j] - prev <= sum 那么一定挤不出sum 个数来给问号,这时候就该输出Incorrect sequence了 = = !
否则的话就要找一个“合适”的num值 赋给第一个问号,后面的问号依次用num ++ 就可以了!
关键就是这个合适的num值如何去找:
因为最后要求数组每一项绝对值之和最小!
可以分类讨论一下:
这时候prev 一定小于 a[j]并且  能“挤出”足够的数给问号!
如果prev >= -1 的话,num 一定要大于等于prev + 1  此时边界num = 0,正好合适
所以if (prev >= -1)num = prev+1
如果a[j] <= 1  num最大是小于等于a[j] -1的 , 此时边界num = 0,可以做到绝对值之和最小!
So   if(a[j] <= 1)num = a[j] - sum;
如果prev 与 a[j]之间既有正数又有负数的话:可以这么想:
首先num一定大于等于prev + 1.  一定要取一个max。
在者,num < a[j] - sum, 还要符合绝对值之和最小,肯定是正负左右分配了(围绕着0 进行分配!)
所以num = max(prev+1,min(-sum/2,a[j]-sum));
最后把这所有连续的问号进行赋值num++即可!
最后就输出咯!~~
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2*100000 + 10;
const int INF = 0x3f3f3f3f;
char s[100];
int a[maxn];
int main(){
    int n,k;
//    printf("%d\n",INF);
    while(scanf("%d %d",&n,&k) == 2){
        for (int i = 1; i <= n; ++i){
            scanf("%s",s);
            if (s[0] == '?')a[i] = INF;
            else a[i] = atoi(s);
        }
        bool ok=true;
        for (int i = n+1; i <= n+k; ++i)a[i] = INF+1;
        for (int i = 1; i <= k; ++i){
            int prev = -INF;
            int sum = 0;
            for (int j = i; j <= n+k; j += k){
                if (a[j] == INF)++sum;
                else {
                    if (a[j] - prev <= sum){
                        ok=false;
                        goto TT;
                    }
                    int num;
                    if (prev >= -1)num = prev+1;
                    else if (a[j] <= 1)num = a[j]-sum;
                    else {
                        num = max(prev+1,min(-sum/2,a[j]-sum));
                    }

                    for (int h = sum; h > 0; --h){
                        a[j-h*k] = num++;
                    }
                    sum = 0;
                    prev = a[j];
                }

            }

        }
        TT:
            if (!ok)printf("Incorrect sequence\n");
            else {
                for (int i = 1; i <= n; ++i){
                    if (i > 1)printf(" ");
                    printf("%d",a[i]);
                }
                printf("\n");
            }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值