• [洛谷Luogu]P1803 线段覆盖问题


    贪心想法题解的各位dalaodalao都讲得很清楚了,在下就提供一种桶排的做法吧。

    因为给出数据范围

    0aibi10000000≤ai<bi≤1000000

    可以想到使用桶排的方式优化。即从快排的O(nlogn)O(nlogn)的复杂度降低到了O(n)O(n)的复杂度。

    需要考虑的问题

    快排是依照右端点直接排序后遍历所有线段,因此并不需要考虑右端点相同时的放置顺序(因为遍历一遍总会遇到),但桶排则需要考虑右端点相同的线段要如何放置。

    显然右端点相同时,左端点更大的线段更有潜力,因此以左端点为第二关键字进行桶排即可。

    #include <cstdio>
    using namespace std;
    struct node
    {
        int l, r;
    } all[1000001];//保存数据的结构体数组
    int s[1000001];//排序数组,保存以右端点位置为下标的线段的编号,即   s[all[i].r] = i
    int n, last, ans, maxr;//last为上次选择的线段的右端点
    //读入优化部分
    inline char nc()
    {
        static char buf[1000000],*p1 = buf,*p2 = buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    void read(int &r)
    {
        static char c; r=0;
        for(c=nc();c>'9'||c<'0';c=nc());
        for(;c>='0'&&c<='9';r=(r<<1)+(r<<3)+(c^48),c=nc());
    }
    //
    int main()
    {
        read(n);
        for (int i = 1; i <= n; ++i)
        {
            read(all[i].l);
            read(all[i].r);
            maxr = maxr < all[i].r ? all[i].r : maxr;//更新最大右端点,即以后枚举的上界
            if (!s[all[i].r] || all[s[all[i].r]].l < all[i].l)//如果桶的当前位置没有线段,直接放入就好了
                s[all[i].r] = i;//否则以左端点为第二关键字进行排序,左端点大的优先级高
        }
        for (int i = 1; i <= maxr; ++i)//枚举桶位置,依次更新答案
            if (s[i] && all[s[i]].l >= last && ++ans)
                last = all[s[i]].r;
        printf("%d", ans);
        return 0;
    }
    
  • 相关阅读:
    如何导出和导入mysql数据(数据迁移)
    C# exe dll防止反编译-- dotNET_Reactor
    C#防止反编译
    WCF异常相关
    了解WCF的前世今生之实现服务端(一)
    svn忽略文件后缀
    马云给年轻人的10句忠告 真的后悔才看到!
    如何利用好清晨与夜间的时间?
    浙江旅游好去处
    突然觉得生活好累......
  • 原文地址:https://www.cnblogs.com/Clouder-Blog/p/12146650.html
Copyright © 2020-2023  润新知