• BZOJ1178 [Apio2009]CONVENTION会议中心 贪心 set


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1178


    题意概括

      一堆线段,现在取出最多条数,使其互不覆盖,并输出字典序最小的方案。


    题解

      这题好坑。

      首先,注意一点,最后不能有多余的空格。

      第一问就是基础的线段覆盖。

      关键在于第二问。

      我们要准备一个函数—— Get_Ans(L,R),用来求解L~R这个区间内,最多可以取多少线段。

      这个可以O(log n)解决。前提是倍增预处理。

      然后就是关键部分。

      我们按照字典序从小到大,能选择就选择。

      怎么判断是否可以选择?只需要在之前选择的线段空隙中可以放这个线段,并且满足Get_Ans(这个线段到它左边的第一条线段之前)+Get_Ans(它到它右边的第一个线段之前)+1 = Get_Ans(他左右两端的),那么就可以放进去。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <set>
    using namespace std;
    const int N=200000+5,Inf=1e9;
    struct seg{
        int L,R;
        bool operator < (const seg x) const {
            if (L==x.L)
                return R>x.R;
            return L<x.L;
        }
    }s[N],s2[N];
    int n,rn,Hash[N*2],hs,p[N][20],L[N];
    bool alive[N],vis[N*2];
    set <int> S;
    void HASH(){
        sort(Hash+1,Hash+hs+1);
        int hs_=1;
        for (int i=2;i<=hs;i++)
            if (Hash[i]!=Hash[i-1])
                Hash[++hs_]=Hash[i];
        hs=hs_;
    }
    void Delete(){
        for (int i=1;i<=n;i++)
            s2[i]=s[i];
        sort(s+1,s+n+1);
        memset(alive,true,sizeof alive);
        int MinR=Inf,n_=0;
        for (int i=n;i>=1;i--)
            if (MinR>s[i].R)
                MinR=s[i].R;
            else
                alive[i]=0;
        for (int i=1;i<=n;i++)
            if (alive[i])
                s[++n_]=s[i];
        n=n_;
    }
    void Get_Pos(){
        memset(p,0,sizeof p);
        for (int i=1;i<=n;i++)
            L[i]=s[i].L;
        L[n+1]=Inf;
        for (int i=1;i<=n;i++){
            p[i][0]=upper_bound(L+1,L+n+2,s[i].R)-L;
            if (p[i][0]==n+1)
                p[i][0]=0;
        }
        for (int i=1;i<=18;i++)
            for (int j=1;j<=n;j++)
                p[j][i]=p[p[j][i-1]][i-1];
    }
    int Get_Ans(int Le,int Ri){
        if (Le>Ri||Le>hs)
            return 0;
        int ans=1,pos=lower_bound(L+1,L+n+2,Le)-L;
        if (pos>n||Ri<s[pos].R)
            return 0;
        for (int i=18;i>=0;i--){
            if (!p[pos][i]||s[p[pos][i]].R>Ri)
                continue;
            pos=p[pos][i];
            ans+=1<<i;
        }
        return ans;
    }
    int main(){
        scanf("%d",&n),rn=n;
        for (int i=1;i<=n;i++){
            scanf("%d%d",&s[i].L,&s[i].R);
            Hash[++hs]=s[i].L;
            Hash[++hs]=s[i].R;
        }
        HASH();
        for (int i=1;i<=n;i++){
            s[i].L=lower_bound(Hash+1,Hash+hs+1,s[i].L)-Hash;
            s[i].R=lower_bound(Hash+1,Hash+hs+1,s[i].R)-Hash;
        }
        Delete();
        Get_Pos();
        printf("%d
    ",Get_Ans(1,hs));
        S.clear();
        S.insert(Inf),S.insert(-Inf);
        bool empty_block=0;
        for (int i=1;i<=rn;i++){
            int now=*S.lower_bound(s2[i].L);
            if (now==Inf||!vis[now]){
                if (now<=s2[i].R)
                    continue;
                int left=*--S.lower_bound(s2[i].L);
                int right=*S.lower_bound(s2[i].R);
                int val=Get_Ans(left+1,s2[i].L-1)+1+Get_Ans(s2[i].R+1,right-1);
                if (val<Get_Ans(left+1,right-1))
                    continue;
                S.insert(s2[i].L);
                S.insert(s2[i].R);
                if (s2[i].L!=s2[i].R)
                    vis[s2[i].R]=1;
                if (empty_block)
                    putchar(' ');
                printf("%d",i);
                empty_block=1;
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    IDEA创建test测试类
    SpringBoot Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration
    Mysql在线加索引锁表归纳
    工作感悟--对上一份工作总结
    ESP8266获取网络NTP时间(转)
    Python中的CGI编程 config配置(windows、Apache) 以及后期的编写(转)
    CGI与FastCGI(转)
    JSON-RPC轻量级远程调用协议介绍及使用
    java插件化编程(动态加载)
    PF4J入门指南
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1178.html
Copyright © 2020-2023  润新知