codeforces 1552E. Colors and Intervals

1552E. Colors and Intervals

https://codeforces.com/contest/1552/problem/E

勉强还算在复建期内…但这场B卡死是真的“真有我的”,CD反而还好


题意:给出 n × k n \times k n×k 个数的颜色,(一共有n种颜色,每种颜色有k个数),要求输出n个区间 [ a i , b i ] [a_i, b_i] [ai,bi],第i个区间端点都是第i种颜色,并且每个数被包括的次数不能超过 ⌈ n k − 1 ⌉ \lceil \frac{n}{k - 1} \rceil k1n

两种做法:

  1. 直接贪心,把每个区间和区间的颜色取出来,根据右端点排序, 每次能取就取

  2. (1)考虑到每个被取的区间中端点的这个颜色不会在除了两端以外出现,每种颜色实际被分成了k-1个块。

    (2)根据(1)中的块,第t块中取的每种颜色的区间的左端点为该颜色第t次出现的位置,对还没有选择的颜色的区间同样根据右端点排序,最多取 ⌈ n k − 1 ⌉ \lceil \frac{n}{k - 1} \rceil k1n个。

    因为 , 在前一块里取的区间可能互相重合但他们不会和后一块里取的区间重合,因为(2)是根据右端点排序取的,在下一块里的左端点是上一块中的右端点,严格不重合。而由于 ⌈ n k − 1 ⌉ × ( k − 1 ) ≥ n \lceil \frac{n}{k - 1} \rceil \times (k - 1) \geq n k1n×(k1)n , 一定能取完n种颜色, 很妙。

#include <bits/stdc++.h>

using namespace std;

const int N = 1e4 + 10;
const int M = 110;

struct node {
    int l, r;
    int co, idx;
};

int c[N];
vector<int> g[M];
vector<node> vec[M]; 
bool vis[M];
pair<int, int> ans[N];

int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n * k; ++i) {
        cin >> c[i];
        g[c[i]].push_back(i);
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j < k; ++j) {
            vec[j].push_back({g[i][j - 1], g[i][j], i, j});
        }
    }
    int ceil = (n + k - 2) / (k - 1);
    for (int i = 1; i < k; ++i) {
        sort(vec[i].begin(), vec[i].end(), [](node x, node y) { return x.r < y.r; });
        int cnt = 0;
        for (int j = 0; j < n; ++j) {
            if(vis[vec[i][j].co]) continue;
            vis[vec[i][j].co] = 1;
            ans[vec[i][j].co] = {vec[i][j].l, vec[i][j].r};
            cnt ++;
            if(cnt >= ceil) break;
        }
    }
    for(int i = 1; i <= n; ++ i) {
        cout << ans[i].first + 1 <<" "<< ans[i].second + 1 << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值