• P2161 [SHOI2009]会场预约


    题目描述

    PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地。这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突。也就是说,前一个会议的结束日期必须在后一个会议的开始日期之前。所以,如果要接受一个新的场地预约申请,就必须拒绝掉与这个申请相冲突的预约。 一般来说,如果PP大厦方面事先已经接受了一个会场预约,例如从10日到15日,就不会在接受与之相冲突的预约,例如从12日到17日。不过,有时出于经济利益,PP大厦方面有时会为了接受一个新的会场预约,而拒绝掉一个甚至几个之前预订的预约。 于是,礼堂管理员QQ的笔记本上笔记本上经常记录着这样的信息: 本题中为方便起见,所有的日期都用一个整数表示。例如,如果一个为期10天的会议从“90日”开始到“99日”,那么下一个会议最早只能在“100日”开始。 最近,这个业务的工作量与日俱增,礼堂的管理员QQ希望参加SHTSC的你替他设计一套计算机系统,方便他的工作。这个系统应当能执行下面两个操作: A操作:有一个新的预约是从“start日”到“end日”,并且拒绝掉所有与它相冲突的预约。执行这个操作的时候,你的系统应当返回为了这个新预约而拒绝掉的预约个数,以方便QQ与自己的记录相校对。 B操作:请你的系统返回当前的仍然有效的预约的总数。

    输入输出格式

    输入格式:

     

    输入文件的第一行是一个整数n,表示你的系统将接受的操作总数。 接下去n行每行表示一个操作。每一行的格式为下面两者之一: “A start end”表示一个A操作; “B”表示一个B操作。

     

    输出格式:

     

    输出文件有n行,每行一次对应一个输入。表示你的系统对于该操作的返回值。

     

    输入输出样例

    输入样例#1: 
    6
    A 10 15
    A 17 19
    A 12 17
    A 90 99
    A 11 12
    B
    输出样例#1: 
    0
    0
    2
    0
    1
    2

    说明

    N< = 200000

    1< = Start End < = 100000

    Solution:

      一道思路特巧妙的题目。

      开始的思路是直接线段树染色,但是要维护的东西比较多,码量大,复杂不想调。

      于是观摩巨佬们的思路,发现本题树状数组+二分的思路实在是巧妙。

      因为每次加入一个区间,就会将与之冲突的区间删去,那么显然同一个$st$或者$ed$只能出现一次。

      我们选择记录当前$st$所对应的$ed$,再用树状数组单点维护每个区间的$st$出现的次数,然后每次需要加入一个区间$[x,y]$,就查找出$(0,y]$中有多少个区间,并二分出离当前区间最近的一个区间的起点,判断一下该区间是否与需要加入的区间有交集,有的话就计数、删掉该区间并继续二分,若无交集,因为区间是一个一个加入的,那么往前的区间一定之前就调整好了,所以再往前不会出现交集,不需要再二分了直接跳出循环。然后将需要加入的区间起点加入树状数组,并记录一下该起点所对应的终点,模拟一下就好了。

      时间复杂度显然$O(nlog^2 n)$(实际肯定是要快的多的,只是单纯从算法嵌套角度分析的最坏情况)。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)>(b)?(b):(a))
    using namespace std;
    const int N=100005;
    int n,sum[N],ed[N],ans,dlt;
    
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
        return f?-a:a;
    }
    
    il void update(int k,int c){while(k<N)sum[k]+=c,k+=k&-k;}
    
    il int query(int k){int ans=0;while(k)ans+=sum[k],k-=k&-k;return ans;}
    
    int main(){
        n=gi();
        char s[3];
        int x,y;
        while(n--){
            scanf("%s",s);
            if(s[0]=='A'){
                x=gi(),y=gi();
                dlt=0;int op;
                while(op=query(y)){
                    int l=0,r=y,m;
                    while(l<r){
                        m=l+r>>1;
                        if(query(m)+1<=op)l=m+1;
                        else r=m;
                    }
                    if(ed[l]>=x)update(l,-1),dlt++,ans--;
                    else break;
                }
                update(x,1),ed[x]=y,ans++;
                printf("%d
    ",dlt);
            }
            else printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    ES基础(五十五)在私有云与公有云上管理与部署 Elasticsearch 集群
    ES基础(五十四)如何对集群进行容量规划
    ES基础(五十二)Hot & Warm 架构与 Shard Filtering
    ES基础(四十九)集群内部安全通信
    ES基础(四十八)集群身份认证与用户鉴权
    kata + docker run & star
    libcontainer nsexec + unshare + syscall(SYS_setns
    docker createHooks
    mount namespace
    exec.Command("/proc/self/exe", "child")
  • 原文地址:https://www.cnblogs.com/five20/p/9246351.html
Copyright © 2020-2023  润新知