CodeForces 518E Arthur and Questions(贪心 + 思维)题解

题意:给你a1~an,k,要求a1 + ... + ak < a2 + .... + ak+1 < a3 + ... + ak+2 <...,然后这里的ai有可能是?,要求你填?的数字,并且使a1~an的绝对值之和最小,不可能输出Incorrect sequence

思路:由上式要求我们可以得到a1 < ak+1 < ak+k+1 < ....且a2 < ak+2 < ak+k+2 < ....且...,所以可以转化为这样的要求。但是要绝对值最小怎么办,我们每次找连续的一连串?,尽可能让中间的位置为0,这样绝对值最小。所以我们先按中间赋值0这样去操作,然后再根据左右边界对整个区间进行修正,全加或全减一个数使得符合要求。

代码:

#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000009;
int n, k, none[maxn];
ll a[maxn];
int id(int j, int k, int i){return j * k + i;}
void solve(int ii, int l, int r){
    int m = (l + r) / 2;
    int num = 0;
    for(int i = m; i <= r; i++)
        a[id(i, k, ii)] = num++;
    num = 0;
    for(int i = m; i >= l; i--)
        a[id(i, k, ii)] = num--;
    int dis;
    if(l != 0){
        dis = a[id(l - 1, k, ii)] - a[id(l, k, ii)];
        if(dis >= 0){
            dis++;
            for(int i = l; i <= r; i++)
                a[id(i, k, ii)] += dis;
        }
    }
    if(id(r + 1, k, ii) <= n){
        dis = a[id(r, k, ii)] - a[id(r + 1, k, ii)];
        if(dis >= 0){
            dis++;
            for(int i = l; i <= r; i++)
                a[id(i, k, ii)] -= dis;
        }
    }
}
int main(){
    char o[20];
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++){
        scanf("%s", o);
        if(o[0] == '?'){
            none[i] = 1;
        }
        else{
            sscanf(o, "%lld", &a[i]);
        }
    }
    for(int i = 1; i <= k; i++){
        int l = 0, r = 0, ok = 0;
        for(int j = 0; j * k + i <= n; j++){
            if(none[id(j, k, i)] && (j == 0 || !none[id(j - 1, k, i)])){
                l = j;
                ok = 1;
            }
            if(none[id(j, k, i)]){
                r = j;
            }
            else{
                if(ok){
                    solve(i, l, r);
                    ok = 0;
                }
            }
        }
        if(ok) solve(i, l, r);
    }

    ll tot = 0, pre;
    for(int i = 1; i <= k; i++){
        tot += a[i];
    }
    pre = tot;
    for(int i = k + 1; i <= n; i++){
        tot = tot - a[i - k] + a[i];
        if(tot <= pre){
            printf("Incorrect sequence\n");
            return 0;
        }
        pre = tot;
    }

    for(int i = 1; i <= n; i++){
        if(i != 1) printf(" ");
        printf("%d", a[i]);
    }
    printf("\n");
    return 0;
}

 

posted @ 2019-04-11 21:59  KirinSB  阅读(178)  评论(0编辑  收藏  举报