• P2161 [SHOI2009]Booking 会场预约


    https://www.luogu.org/problem/show?pid=2161

    这里写图片描述

    题意简析:你需要写一个数据结构,维护一个时间轴,支持如下操作:

    1)插入1个新区间,删除所有时间轴上与它有交的区间并输出个数。

    2)查询当前时间轴上的区间个数。

    我们可以用线段树来做(借鉴了sxb大神的代码)。离线处理。用线段树存序号的最小值。
    当我们倒着插入第i号区间之前,在线段树里取最小值,那么当前插入的这个区间会影响到序号为查询出的最小值的这个区间,用ans[i]表示插入第i个区间时,有几个矛盾的区间。

    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    #define M 100010
    #define N 200010
    using namespace std;
    int n,ans[N],al[N],ar[N],Q[N];
    int a[4*M],m[4*M];
    void pushdown(int o)
    {
        m[o<<1]=min(m[o],m[o<<1]);a[o<<1]=min(a[o<<1],m[o<<1]);
        m[o<<1|1]=min(m[o],m[o<<1|1]);a[o<<1|1]=min(a[o<<1|1],m[o<<1|1]);
    }
    void change(int o,int l,int r,int ql,int qr,int k)
    {
        int mid=(l+r)>>1;
        if(ql<=l&&qr>=r) 
        {
            m[o]=min(m[o],k);
            a[o]=m[o];
            return ;
        }
        if(a[o]!=a[0]) pushdown(o);
        if(ql<=mid) change(o<<1,l,mid,ql,qr,k);
        if(qr>mid) change(o<<1|1,mid+1,r,ql,qr,k);
        a[o]=min(a[o<<1],a[o<<1|1]);
    }
    int query(int o,int l,int r,int ql,int qr)
    {
        int mid=(l+r)>>1;
        if(ql<=l&&qr>=r) return a[o];
        if(a[o]!=a[0]) pushdown(o);
        int minn=a[0];
        if(ql<=mid) minn=min(minn,query(o<<1,l,mid,ql,qr));
        if(qr>mid) minn=min(minn,query(o<<1|1,mid+1,r,ql,qr));
        return minn;
    }
    int main()
    {
        scanf("%d",&n);
        memset(a,127,sizeof(a));memset(m,127,sizeof(m));
        for(int i=1;i<=n;i++)
        {
            char P;
            cin>>P;
            if(P=='A') 
            {
                Q[i]=1;
                scanf("%d%d",&al[i],&ar[i]);
            }
        }
        for(int i=n;i>=1;i--)
        if(Q[i])
        {
            int tmp=query(1,1,N-10,al[i],ar[i]);
            if(tmp!=a[0]) ans[tmp]++;
            change(1,1,N-10,al[i],ar[i],i);
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(Q[i]) sum=sum+1-ans[i],printf("%d
    ",ans[i]);
            else printf("%d
    ",sum);
        }
        return 0;
    }
    

    还有就是set的做法。
    当读入一个新的预约时,不断查找已经存在的预约中end值大等于新预约start值,并且最接近该start值的预约,找到一个删除一个,直到不能删除为止。因为不冲突的预约都是不相互覆盖的,所以它们的start值与end值必然是递增序列,所以一旦一个预约不能删除,后面的预约也不能删除。
    注意set中的元素的定义和set排序的原则。
    建议画图理解。

    #include<iostream>
    #include<cstdio>
    #include<set>
    using namespace std;
    struct H{
        int L,R;
        bool operator <(const H&a) const{
            if(a.R==R) return L<a.L;
            return R<a.R;
        }
    };
    set <H> s;
    int n;
    int main()
    {
        set<H>::iterator it;
        char P;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            cin>>P;
            if(P=='A')
            {
                int l,r,ans=0;
                scanf("%d%d",&l,&r);
                while(1)
                {
                    it=s.lower_bound((H){0,l});
                    if(it!=s.end()&&it->L<=r)
                    {
                        ans++;
                        s.erase(it);
                        continue;
                    }
                    else{
                        s.insert((H){l,r});
                        break;
                    }
                }
                printf("%d
    ",ans);
            }
            else printf("%d
    ",s.size());
        }
        return 0;
    }
  • 相关阅读:
    struct resbuf 结构就象LISP里面的表(
    CString互转int
    C++中std::sort/std::stable_sort/std::partial_sort的区别及使用
    *ARX对数据的类型和单位进行转换
    c++常见容器操作
    C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!
    ARX 简单程序(不错的例子)
    ARX对象的一些文字说明
    CAD ObjectARX扩展工具的源码(一)
    CAD ObjectARX扩展工具的源码(三)
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587865.html
Copyright © 2020-2023  润新知