bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心
[Apio2009]CONVENTION会议中心
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 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
4 9
9 11
13 19
10 17
Sample Output
2
1 3
1 3
HINT
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 }