hdu6301--Distinct Values--多校补题 贪心+set维护

题意:让你求一个长度为n的数列,数列的条件满足给得m个区间里面数字两两不同,且字典序最小

条件:1 满足给得m个区间里面数字两两不同,会互相重叠

            2 字典序最小,在两两不同的必要区间中从1递增

思路:贪心,m个区间里面数字两两不同,重叠出最大的区间。然后用set存取1-n个数字(set本身就会自己排序,每次取可以取数字最小的),维护每一个区间。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <list>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <set>
using namespace std;
const int maxn=1e5;
int ans[maxn],pre[maxn];//ans用来存储答案,pre用来储存该点的范围
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(ans,0,sizeof(ans));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            pre[i]=i;
        for(int i=1;i<=m;i++)
        {
            int l,r;
            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]);
        set<int>s;
        for(int i=1;i<=n;i++)//最多数字1-n,set自己也排好了序
            s.insert(i);
        int p=1;//上一个范围
        for(int i=1;i<=n;i++)
        {
            while(p<pre[i])
            {
                s.insert(ans[p]);
                p++;
            }
            ans[i]=*s.begin();
            s.erase(ans[i]);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d",ans[i]);
            if(i!=n)
                printf(" ");
        }
        printf("\n");
    }
    return 0;
}

总结:1 多校的时候,一直在想怎么用数组取维护,一直超时,没有想到用set维护。

猜你喜欢

转载自blog.csdn.net/qq_40306845/article/details/81180385
今日推荐