Codeforces 980C Posterized(贪心)

题目链接:Posterized

题意

给出 n n 个整数和一个阈值 k,所有整数都在 [0,255] [ 0 , 255 ] 的范围内,要求将所有整数分到一个不阈值大于 k k 的区间内,并从这个阈值内选出一个数字代表这个阈值中的所有数字,[0,255] 内每个整数都只能属于一个阈值,问将 n n 个整数都用所属阈值的代表数字替换后,字典序最小的结果。

输入

第一行为两个整数 n,k (1n105,1k256),第二行为 n n 个整数 p1,p2,,pn (0pi255)

输出

输出字典序最小的结果。

样例

输入
4 3
2 14 3 4
输出
0 12 3 3
提示
2 2 属于 [0,2],代表数字为 0 0 14 属于 [12,14] [ 12 , 14 ] ,代表数字为 12 12 3,4 3 , 4 属于 [3,5] [ 3 , 5 ] ,代表数字为 3 3 ,即得到最小字典序结果。
输入
5 2
0 2 1 255 254
输出
0 1 1 254 254

题解

最初每个数字都属于自身阈值(长度为 1),从前往后,每碰到一个数字,先检查这个数字是否已经属于某一个阈值,如果已经属于,则只能用该阈值的代表数字替换,否则往前找 k1 k − 1 个数字,保证前 x (xk1) x   ( x ≤ k − 1 ) 个数字都没有属于某阈值的情况下,贪心地找到最小的能代表的数字,将这一段的代表数字同设置为该数字,一直往后。

过题代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
using namespace std;

#define LL long long
const int maxn = 100000 + 100;
int n, k;
int num[maxn];
int head[1000];

int Find(int x) {
    int ret = x;
    int kk = k;
    while(ret != 0) {
        --ret;
        --kk;
        if(head[ret] != -1) {
            ++ret;
            break;
        }
        if(kk == 0) {
            ++ret;
            break;
        }
    }
    if(ret == 0) {
        return ret;
    }
    if(x - head[ret - 1] + 1 <= k) {
        return head[ret - 1];
    } else {
        return ret;
    }
}

int main() {
    #ifdef LOCAL
    freopen("test.txt", "r", stdin);
//    freopen("testout.txt", "w", stdout);
    #endif // LOCAL
    ios::sync_with_stdio(false);

    while(scanf("%d%d", &n, &k) != EOF) {
        memset(head, -1, sizeof(head));
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &num[i]);
            if(head[num[i]] != -1) {
                continue;
            }
            int Index = Find(num[i]);
            for(int j = Index; j <= num[i]; ++j) {
                head[j] = Index;
            }
        }
        for(int i = 1; i <= n; ++i) {
            if(i != 1) {
                printf(" ");
            }
            printf("%d", head[num[i]]);
        }
        printf("\n");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值