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;
}

猜你喜欢

转载自blog.csdn.net/hanyanwei123/article/details/81275213