HDU - 6301 Distinct Values(set)

题意:

t组数据,每组数据给定n,m,

表示有m个约束,每个约束包含 x,y ,代表区间 [x, y] 里的数字不能相同。

让你用所有的正整数构成一个长度为 n 的区间,使得这个区间元素顺序的字典序最小。

 

 

 

这个题场上的思路是把所有的约束区间排序,然后再用优先队列维护当前可用的最小值。

后来看了dls的代码。发现我们真是弱爆了。

 

用suc[i]表示每一个左边界为 i 的限制最右可以向右延伸到哪里。

刚开始suc[i] = i; 表示每一个[i, i] 也是一个限制。

例如第三个样例:n = 5, m = 2: [1, 3] [2, 4] 中,suc[i] = { , 3, 4, 3, 4, 5] 

用set维护当前可用的数字。开始时加入1~n。

用一个指针 r 代表当前填数到的位置。若 r <= suc[i] , 代表当前这个限制还没有填完数,继续向下执行,把用过的数字从set中删掉。

用一个L指针记录上一个处理过的区间的起始位置,填好的数组中[L,i-1]内的数值,是可以再次使用的,重新加入set中。

巧妙的是,若r < suc[i] ,代表着有一个新的限制从i 开始。

 

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <set>
using namespace std;

#define maxn 100000 + 100


int main()
{
    int t;
    scanf("%d", &t);
    for (int i = 1; i <= t; i++)
    {
        int n, m, a[maxn], suc[maxn];
        scanf("%d%d", &n, &m);

        for (int i = 1; i <= n; i++)
            suc[i] = i;

        for (int i = 1; i <= m; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            suc[u] = max(suc[u], v);
        }

        set<int> st;
        for (int i = 1; i <= n; i++)
            st.insert(i);

        int l = 1, r = 1;
        for (int i = 1; i <= n; i++)
        {
            if (suc[i] < r) continue;
            while(l < i) st.insert(a[l++]);
            while(r <= suc[i])
            {
                a[r] = *st.begin();
                st.erase(a[r++]);
            }
        }

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

 

posted @ 2018-07-24 19:27  jvruodejrLS  阅读(213)  评论(0编辑  收藏  举报

Contact with me