bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心

[Apio2009]CONVENTION会议中心

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1130  Solved: 444
[Submit][Status][Discuss]

Description

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)。 你的任务是帮助销售主管确定应该将会堂租借给哪些公司。

Input

第一行有一个整数N,表示发出租借会堂申请的公司的个数。
第2到第N+1行每行有2个整数。第i+1行的整数表示第i家公司申请租借的起始和终止日期。
对于每个公司的申请,起始日期为不小于1的整数,终止日期为不大于10^9的整数。
N≤200000

Output

输出的第一行应有一个整数M,表示最多可以租借给多少家公司。
第二行应列出M个数,表示最终将会堂租借给哪些公司。

Sample Input

4
4 9
9 11
13 19
10 17

Sample Output

2
1 3

HINT

 

修复数据bug,并新加数据一组By NanoApe 2016.5.11


修复后数据:JudgeOnline/upload/201605/dd.rar

 

 

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<set>
 7 
 8 #define inf 1000000007
 9 #define N 200007
10 using namespace std;
11 inline int read()
12 {
13     int x=0,f=1;char ch=getchar();
14     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
15     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 
19 int n,m;
20 int X[N],Y[N],next[N][30],L[N],R[N];
21 struct data
22 {
23     int l,r;
24     friend bool operator < (const data &x,const data &y)
25     {
26         return x.r==y.r ? x.l>y.l : x.r<y.r;
27     }
28 }a[N],t[N];
29  
30 int cal(int l,int r) {
31     int x=lower_bound(X+1,X+1+m,l)-X;
32     if (Y[x]>r || x>m) return 0;
33     int res=1;
34     for (int i=20;i>=0;i--) if (next[x][i] && Y[next[x][i]]<=r) res+=1<<i,x=next[x][i];
35     return res;
36 }
37 int main()
38 {
39     n=read();
40     for (int i=1;i<=n;i++)
41         t[i].l=read(),t[i].r=read(),a[i]=t[i];
42     sort(t+1,t+1+n);
43     
44     m=0;
45     for (int i=1;i<=n;i++) 
46         if (m==0||t[i].l>t[m].l) t[++m]=t[i];
47     for (int i=1;i<=m;i++) 
48         X[i]=t[i].l,Y[i]=t[i].r;
49     for (int i=1,j=1;i<=m;i++)
50     {
51         while (j<=m&&t[j].l<=t[i].r) j++;
52         if (j<=m) next[i][0]=j;
53     }
54     for (int j=1;j<=20;j++)
55         for (int i=1;i<=m;i++)
56             next[i][j]=next[next[i][j-1]][j-1];
57     int ans;
58     printf("%d\n",ans=cal(-inf,inf));
59     set<data> s;
60     s.insert((data){inf,inf});
61     s.insert((data){-inf,-inf});
62     int cnt=0;
63     for (int i=1;i<=n;i++)
64     {
65         set<data>::iterator x=s.lower_bound(a[i]),y=x;y--;
66         int l1=y->r,r1=a[i].l,l2=a[i].r,r2=x->l;
67         if (l1>=r1||l2>=r2) continue;
68         if (cal(l1+1,r2-1)==cal(l1+1,r1-1)+cal(l2+1,r2-1)+1)
69         {
70             if (++cnt==ans) printf("%d",i);
71             else printf("%d ",i);
72             s.insert(a[i]);
73         }
74     }
75 }

 

posted @ 2018-04-09 15:37  Kaiser-  阅读(297)  评论(0编辑  收藏  举报