HDU6301 Distinct Value set+贪心

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6301
Distinct Values
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3894 Accepted Submission(s): 1303

Problem Description
Chiaki has an array of npositive integers. You are told some facts about the array: for every two elements aiand aj
in the subarray al..r(l ≤ i< j ≤r), ai≠aj holds.
Chiaki would like to find a lexicographically minimal array which meets the facts.

Input
There are multiple test cases. The first line of input contains an integer
T, indicating the number of test cases. For each test case:

The first line contains two integers nand m(1≤n,m≤105) – the length of the array and the number of facts. Each of the next mlines contains two integers liand ri(1≤li≤ri≤n).

It is guaranteed that neither the sum of all nnor the sum of all mexceeds 106
.

Output
For each test case, output nintegers denoting the lexicographically minimal array. Integers should be separated by a single space, and no extra spaces are allowed at the end of lines.

Sample Input
3
2 1
1 2
4 2
1 2
3 4
5 2
1 3
2 4

Sample Output
1 2
1 2 1 2
1 2 3 1 1

题解:
题目大意是给n个大小的数组,m个区间条件[l,r],使区间内不能重复,求最小的字典序列
贪心策略:pre[i]数组存以i为右区间端点能到最左边的位置,当相同终点时,小区间将被大区间包含pre[r]=min(pre[r],l)
如 5 2
2 5
3 5
pre:1 2 2 2 2
样例三:
5 2
1 3
2 4
pre:1 1 1 2 5
set可以自动排序,用set维护可以用的数
pl记录上一步位置
ans数组存结果
因为pre[]数组的每一个位置存与当前不能重复的左区间端点,不能重复的区间pre的值相同,所以当进入某一段区间时,pl等于该区间段的左区间点位置,
当pl

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<set>
#define ll long long
using namespace std;

int T,n,m,l,r,pre[100005],ans[100005];
int main()
{
    scanf("%d",&T);
    while(T--){
        memset(pre,0,sizeof(pre));
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            pre[i]=i;
        for(int i=0;i<m;i++){
            scanf("%d %d",&l,&r);
            pre[r]=min(pre[r],l);
        }

        for(int i=n-1;i>=1;i--)
            pre[i]=min(pre[i],pre[i+1]);
        //pre表示不能重复的区域pre[i]=l
        //pl到pre[i-1]能重复,即当pl<pre[i]时,
        //for(int i=1;i<=n;i++)
        //    printf("%5d",pre[i]);
        //cout << endl;
        int pl=1;//从1开始
        set<int>s;
        for(int i=1;i<=n;i++)
            s.insert(i);
        for(int i=1;i<=n;i++){
            while(pl<pre[i]){
                s.insert(ans[pl]);
                pl++;
            }
            ans[i]=*s.begin();
            s.erase(ans[i]);
        }

       printf("%d",ans[1]);
       for(int i=2;i<=n;i++)
            printf(" %d",ans[i]);
        cout<< endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值