2018 Multi-University Training Contest 1 D-Distinct Values(优先队列)

这里写图片描述

题意:让你在保证m组闭区间内的数字都不同的前提下,生成一个长度为n,字典序最小的数列。

字典序最小,就是让开头的数字尽可能的小,所以我们要尽可能的填1,填不了1再填2、填3、4….

所以,没有区间束缚的位置,我们全填上1。

有区间束缚的位置,我们也要尽可能的填1,但是他要求区间内没有重复,这就要求我们在对一个区间进行填充的时候,从小到大维护这个区间内能填充的值。

当然是优先队列啦。

优先队列在这里能做到:保证区间内值不重复(出队)、保证字典序最小(始终保持顶端有序)、将区间结束后释放出来的数字及时使用。

所以,用结构体存储区间并按左边界排序,再用优先队列维护能填的数字就可以了!

更多的细节看代码的注释吧。

ac代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 1e5 + 5;

struct Seg {
    int l, r;

    bool operator < (const Seg &a) const {
        return l < a.l;
    }

} Segs[maxn];


int main() {
    int t, n, m, num[maxn];
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i++) {
            scanf("%d%d", &Segs[i].l, &Segs[i].r);
        }
        sort(Segs, Segs + m);

        priority_queue<int, vector<int>, greater<int> > wait;
        for(int i = 1; i <= n; i++) {
            wait.push(i);//将可以填的数字全部入队
        }

        memset(num, 0, sizeof(num));

        int pre = -1;//前一个区间的索引
        for(int i = 0; i < m; i++) {
            Seg get = Segs[i];

            //试想,如果一个区间被另一个区间所涵盖,就不用考虑这个区间了对吧?
            //由于已经按左边界排序,所以只考虑右边界,跳过包含区间。
            if(num[get.r] > 0) {
                continue;
            }

            //释放操作,及时释放被前一个区间占用的数字(入队)
            //如果两个区间有重合,则只释放到现在区间的左边界 - 1
            if(pre != -1) {
                for(int j = Segs[pre].l; j <= Segs[pre].r && j < Segs[i].l; j++) {
                    wait.push(num[j]);
                }
            }

            // 考虑区间重合的情况,从没填的部分开始
            int j = get.l;
            if(pre != -1) {
                j = max(j, Segs[pre].r + 1);
            }
            for(; j <= get.r; j++) {
                num[j] = wait.top();
                wait.pop();
            }

            pre = i;
        }

        for(int i = 1; i <= n; i++) {
            // 没有被区间束缚的部分,在输出时就能顺手填1
            if(num[i] == 0) {
                num[i] = 1;
            }
            printf("%d", num[i]);
            if(i < n) {
                printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cymbals/article/details/81177316