首页 > 编程语言 >蓝桥杯 ALGO-40算法训练 会议中心 (APIO 2009)

蓝桥杯 ALGO-40算法训练 会议中心 (APIO 2009)

时间:2022-12-02 17:01:15浏览次数:52  
标签:租借 include return int 40 next 蓝桥 会堂 2009

时间限制:2.0s 内存限制:512.0MB
关键字:APIO 2009
会议中心  Siruseri政府建造了一座新的会议中心。许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议。
  对于一个客户而言,仅当在开会时能够独自占用整个会堂,他才会租借会堂。会议中心的销售主管认为:最好的策略应该是将会堂租借给尽可能多的客户。显然,有可能存在不止一种满足要求的策略。
  例如下面的例子。总共有4个公司。他们对租借会堂发出了请求,并提出了他们所需占用会堂的起止日期(如下表所示)。

          开始日期  结束日期
    公司1    4       9
    公司2    9       11
    公司3    13      19
    公司4    10      17

  上例中,最多将会堂租借给两家公司。租借策略分别是租给公司1和公司3,或是公司2和公司3,也可以是公司1和公司4。注意会议中心一天最多租借给一个公司,所以公司1和公司2不能同时租借会议中心,因为他们在第九天重合了。
  销售主管为了公平起见,决定按照如下的程序来确定选择何种租借策略:首先,将租借给客户数量最多的策略作为候选,将所有的公司按照他们发出请求的顺序编号。对于候选策略,将策略中的每家公司的编号按升序排列。最后,选出其中字典序最小[1]的候选策略作为最终的策略。
  例中,会堂最终将被租借给公司1和公司3:3个候选策略是{(1,3),(2,3),(1,4)}。而在字典序中(1,3)<(1,4)<(2,3)。
  你的任务是帮助销售主管确定应该将会堂租借给哪些公司。
输入格式
  输入的第一行有一个整数N,表示发出租借会堂申请的公司的个数。第2到第N+1行每行有2个整数。第i+1行的整数表示第i家公司申请租借的起始和终止日期。对于每个公司的申请,起始日期为不小于1的整数,终止日期为不大于109的整数。
输出格式
  输出的第一行应有一个整数M,表示最多可以租借给多少家公司。第二行应列出M个数,表示最终将会堂租借给哪些公司。
数据规模和约定
  对于50%的输入,N≤3000。在所有输入中,N≤200000。
样例输入
4
4 9
9 11
13 19
10 17
样例输出
2
1 3

[1] 字典序指在字典中排列的顺序,如果序列l1是序列l2的前缀,或者对于l1和l2的第一个不同位置j,l1[j]

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=200010;
struct data {
    int l,r;
    friend bool operator < (const data &x,const data &y) {
        return x.r==y.r ? x.l>y.l : x.r<y.r;
    }
}a[maxn],t[maxn];
int X[maxn],Y[maxn],next[maxn][30],L[maxn],R[maxn],n,m;

int cal(int l,int r) {
    int x=lower_bound(X+1,X+1+m,l)-X;
    if (Y[x]>r || x>m) return 0;
    int res=1;
    for (int i=20;i>=0;i--) if (next[x][i] && Y[next[x][i]]<=r) res+=1<<i,x=next[x][i];
    return res;
}
int main() {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d%d",&t[i].l,&t[i].r),a[i]=t[i];
    sort(t+1,t+1+n);
    m=0;
    for (int i=1;i<=n;i++) if (m==0 || t[i].l>t[m].l) t[++m]=t[i];
    for (int i=1;i<=m;i++) X[i]=t[i].l,Y[i]=t[i].r;
    for (int i=1,j=1;i<=m;i++) {
        while (j<=m && t[j].l<=t[i].r) j++;
        if (j<=m) next[i][0]=j;
    }
    for (int j=1;j<=20;j++)
        for (int i=1;i<=m;i++) next[i][j]=next[next[i][j-1]][j-1];
    int ans;
    printf("%d\n",ans=cal(-inf,inf));
    set<data> s;
    s.insert((data){inf,inf});
    s.insert((data){-inf,-inf});
    int cnt=0;
    for (int i=1;i<=n;i++) {
        set<data>::iterator x=s.lower_bound(a[i]),y=x;y--;
        int l1=y->r,r1=a[i].l,l2=a[i].r,r2=x->l;
        if (l1>=r1 || l2>=r2) continue;
        if (cal(l1+1,r2-1)==cal(l1+1,r1-1)+cal(l2+1,r2-1)+1) {
            if (++cnt==ans) printf("%d",i);
            else printf("%d ",i);
            s.insert(a[i]);
        }
    }
    return 0;
}

C++:

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <set>

const char fi[] = "convention.in";
const char fo[] = "convention.out";
const int maxN = 200010;
const int MAX = 0x3f3f3f3f,MIN = ~MAX;

struct Seg
{
    int L,R;
    Seg()
    {
    }
    Seg(int L,int R): L(L),R(R)
    {
    }
    bool operator<(const Seg &b) const
    {
        return L < b.L || L == b.L && R < b.R;
    }
};
std::set <Seg> S;
std::set <Seg>::iterator iter;
Seg req[maxN],seg[maxN],tmp[maxN];
int tab[maxN << 1],next[20][maxN << 1];
int n,cnt,Lim = 1,logLim;

void init_file()
{
    return;
}

inline int getint()
{
    int res = 0; char tmp;
    while(!isdigit(tmp = getchar()));
    do res = (res << 3) + (res << 1) + tmp - '0';
    while(isdigit(tmp = getchar()));
    return res;
}

void readdata()
{
    n = getint();
    for(int i = 0; i < n; ++i)
    {
        int L = getint(),R = getint();
        req[i] = Seg(L,R);
        tab[i << 1] = L;
        tab[(i << 1) + 1] = R;
    }
    return;
}

int plc(int x)
{
    for(int L = 0,R = Lim - 1; L < R + 1;)
    {
        int Mid = (L + R) >> 1;
        if(x == tab[Mid]) return Mid + 1;
        if(x < tab[Mid]) R = Mid - 1;
        else L = Mid + 1;
    }
}

bool cmp(const Seg &a,const Seg &b)
{
    return a.R < b.R || a.R == b.R && a.L > b.L;
}

void discrete()
{
    std::sort(tab,tab + (n << 1));
    for(int i = 1; i < n << 1; ++i)
        if(tab[i] != tab[i - 1])
            tab[Lim++] = tab[i];
    for(int i = 0; i < n; ++i)
        tmp[i] = req[i] = Seg(plc(req[i].L),
        plc(req[i].R));
    std::sort(tmp,tmp + n,cmp);
    //这里必须要用一个临时数组,
    //保证左界右界同时单调递增。
    int p = 0; seg[cnt++] = tmp[0];
    for(int i = 1; i < n; ++i)
        if(tmp[i].L > tmp[p].L)
            seg[cnt++] = tmp[p = i];
    return;
}

void next_set()
{
    int p = cnt; next[0][Lim + 1] = MAX;
    for(int j = Lim; j; --j)
        if(p > -1 && j == seg[p - 1].L)
            next[0][j] = seg[--p].R + 1;
        else next[0][j] = next[0][j + 1];
        for(int i = 0;; ++i)
        {
            bool flag = 0;
            next[i + 1][Lim + 1] = MAX;
            for(int k = 1; k < Lim + 1; ++k)
            {
                if(next[i][k] == MAX)
                    next[i + 1][k] = MAX;
                else next[i + 1][k] = next[i][next[i][k]];
                if(next[i + 1][k] < MAX) flag = 1;
            }
            if(!flag)
            {
                logLim = i; break;
            }
        }
        return;
}

int max_time(int L,int R)
{
    if(L > R++) return 0;
    int ans = 0,p = L;
    for(int i = logLim; i > -1 && p < R; --i)
        if(next[i][p] <= R)
        {
            p = next[i][p]; ans += 1 << i;
        }
    return ans;
}

bool query(int i)
{
    int L = req[i].L,R = req[i].R;
    iter = S.lower_bound(Seg(L,MAX));
    if(iter-- == S.begin()) return 0;
    if(iter->L > L || iter->R < R)
        return 0;
    int L1 = iter->L,R1 = iter->R;
    if(max_time(L1,L - 1)
        + max_time(R + 1,R1)
        + 1 < max_time(L1,R1))
        //这里要满足放进去过后不影响总的答案。
        return 0;
    S.erase(iter);
    if(L1 < L) S.insert(Seg(L1,L - 1));
    if(R < R1) S.insert(Seg(R + 1,R1));
    return 1;
}

void work()
{
    printf("%d\n",max_time(1,Lim));
    S.insert(Seg(1,Lim));
    for(int i = 0; i < n; ++i)
        if(query(i))
            printf("%d ",i + 1);
    printf("\n");
    return;
}

int main()
{
    init_file();
    readdata();
    discrete();
    next_set();
    work();
    return 0;
}

标签:租借,include,return,int,40,next,蓝桥,会堂,2009
From: https://blog.51cto.com/linmengmeng/5907236

相关文章

  • 蓝桥杯 ALGO-55算法训练 矩阵加法
    时间限制:1.0s内存限制:512.0MB问题描述给定两个N×M的矩阵,计算其和。其中:N和M大于等于1且小于等于100,矩阵元素的绝对值不超过1000。输入格式输入数......
  • 蓝桥杯 ALGO-45算法训练 调和数列问题
    问题描述输入一个实数x,求最小的n使得,1/2+1/3+1/4+…+1/(n+1)>=x。输入的实数x保证大于等于0.01,小于等于5.20,并且恰好有两位小数。你的程序要能够处理多组数据,即......
  • 蓝桥杯 ALGO-34算法训练 纪念品分组
    时间限制:1.0s内存限制:256.0MB关键字:贪心排序问题描述元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值相对......
  • ensp 报错 40 应急解决办法
    问题是这样的,在ensp启动路由器的时候发现报错,查看日志是因为虚拟机注册异常导致。      现提供以下办法应急解决该问题。1、查看现象是否为启动40报错。 ......
  • KBL406-ASEMI插件整流桥KBL406
    编辑:llKBL406-ASEMI插件整流桥KBL406型号:KBL406品牌:ASEMI封装:KBL-4特性:整流桥正向电流:4A反向耐压:600V恢复时间:>2000ns引脚数量:4芯片个数:4芯片尺寸:84MIL浪涌电流:120A 漏电流:>......
  • KBL406-ASEMI插件整流桥KBL406
    编辑:llKBL406-ASEMI插件整流桥KBL406型号:KBL406品牌:ASEMI封装:KBL-4特性:整流桥正向电流:4A反向耐压:600V恢复时间:>2000ns引脚数量:4芯片个数:4芯片尺寸:84MIL浪涌电......
  • 强烈推荐:240多个jQuery插件
    概述jQuery是继prototype之后又一个优秀的Javascript框架。其宗旨是—写更少的代码,做更多的事情。它是轻量级的js库(压缩后只有21k),这是其它的js库所不​​​​......
  • Win10升Win11后出现的文件系统错误-1073740771的几种可能解决办法
    可能性1有服务没能启动键盘按“WIN+R”打开“运行”对话框在对话框输入“services.msc”点击“确定”按钮。会出现如下界面。下拉至Windows部分,找到“WindowsLicens......
  • dblogin登陆数据库时报错ORA-04060
    问题描述:dblogin登陆数据库时报错ORA-04060,如下所示:oracle:11.2.0.4GGSCI(leo-11g-ogg)5>dbloginuseridogg,passwordogg2022-12-0112:19:49WARNINGOGG-25108Fail......
  • python之路40 前端之 CSS 标签查询
    表单标签的补充说明基于form表单发送数据1.用于获取用户数据的标签至少应该含有name属性name属性相当于字典的键用户输入的数据会被保存到标签的value属性中......