HDU - 6301 Distinct Values 优先队列+贪心

题目链接

题意:多组数据,每组数据 n n n 个数,每组数据给出 m m m 个区间,对于每个区间,区间内所有数都互不相等。求一种给 n n n 个数设置值,且这个值 x x x [ 1 , n ] [1,n] [1n] 内的方法,若有多种,求字典序最小的一种。

思路:

1.先考虑字典序最小,对于当前要填数字的这一位数,我们在它所能填写的数中选数字最小的,然后考虑下一位,即可保证求出来的答案是字典序最小的了。

2.求当前位置能填的数字,对每个位置设置一个 p r e pre pre 的数组,存放其位置所处的区间中最左边的端点,那么只要是不属于最左边端点到这个位置前一个位置上的数字都可以填,用优先队列来维护这些数字,填入的数字出队,不属于最左边端点到这个位置前一个位置上且不在队列中的数字入队即可。

#include<iostream>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
#define NUM 100005
int n, m, T;
int a[NUM], pre[NUM];
int num[NUM];
priority_queue<int, vector<int>, greater<int> > q;
inline void AC()
{
    cin >> T;
    int p, l, r;
    while(T--)
    {
        cin >> n >> m;
        while(!q.empty())
            q.pop();
        for (int i = 1; i <= n; ++i)
        {
            num[i] = 0, q.push(i);
            pre[i] = i;//初始化:相当于有n个长度为1的区间
        }
        p = 1;//指向上一个位置所在区间没有覆盖到的最右边的位置
        while (m--)
        {
            scanf("%d%d", &l, &r);
            pre[r] = min(pre[r], l);//求以当前位置为右端点的最左边端点
        }
        for (int i = n - 1; i > 0; --i)//求每个位置所在区间的最左边端点
            pre[i] = min(pre[i], pre[i + 1]);
        for (int i = 1; i <= n; ++i)
        {
            while (p < pre[i])//更新,从上一个最右边位置到当前最右边位置中可以填入的数字
            {
                --num[a[p]];
                if (num[a[p]] == 0)
                    q.push(a[p]);
                ++p;
            }
            a[i] = q.top(), q.pop(), ++num[a[i]];//弹出可以填的最小的数字
            printf("%d", a[i]);
            if (i != n)
                printf(" ");
        }
        printf("\n");
    }
}
int main()
{
    AC();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值