Codeforces #480 (Div. 2) 解题报告 C. Posterized 贪心

题意:一共有256个像素格,你可以将这些像素格分组,每个分组小于等于K。

        给出n个像素格,像素格以其所在分组内的一个像素表示,就是每个分组对应一个组名(像素格的数值),求给出的数的对应的组名的字典序最小的情况。


题解:

1、贪心,想办法在满足条件的情况下让相应的组名取得更小的值

2、分情况贪心,首先让所有的像素都未分组,然后按照给出的数一个一个地进行分组

3、最简单的情况就是该组已经被分到了某一组,那答案就是组名

4、选出max(0,p[i] - k + 1)到 p[i] 区间,判断区间左边是否被分组,或者是否独立成组。如果区间未分组或者独立成组(组名是自己),那么表示整个区间都可以表示为区间最左边的值(即整个区间成组)

5、依然选出如上区间,从右往左找到在区间内的一个分组,那么把区间有半部分都归入这个分组

6、如上区间,右往左找不到分组,就把整个区间都成组,组名为区间左边对应的值

#include <bits/stdc++.h>
using namespace std;
const int maxn = 260,maxm = 100000 + 10;
int group[maxn],p[maxm];

int main() {
    int n,k,x;
    memset(group,-1,sizeof(group));
    cin >> n >> k;
    for(int i = 0;i < n;i++)
        cin >> p[i];
    for(int i = 0;i < n;i++) {
        if(group[p[i]] != -1)          //该数字已经有所属组,直接输出组名
            cout << group[p[i]] << " ";
        else {                         //该数字还没有分组
            int j,tag = p[i] - k + 1;  //tag表示可能区间左下标
            tag = max(0,tag);          //保证下标在正常范围
            //区间左下标没有分组,那么直接让整个区间成组,组名等于左下标
            if(group[tag] == tag || group[tag] == -1) {
                for(j = tag;j <= p[i];j++)
                    group[j] = tag;
                cout << group[p[i]] << " ";
            }
            //区间左下标有分组并且组名不等于左下标
            else {
                for(j = p[i];j >= tag;j--)  //搜索区间内最右边的分组
                    if(group[j] != -1)
                        break;
                if(group[j] > tag) tag = group[j];  //区间内存在分组,就让后半部分纳入该分组
                else tag = j + 1;           //区间内没有分组,让整个区间成组,组名等于左下标
                for(j = tag;j <= p[i];j++)
                    group[j] = tag;
                cout << group[p[i]] << " ";
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a912952381/article/details/80273905