【BZOJ】【1178】【APIO2009】convention会议中心

贪心


  如果不考虑字典序的话,直接按右端点排序,能选就选,就可以算出ans……

  但是要算一个字典序最小的解就比较蛋疼了= =

  Orz了zyf的题解

  就是按字典序从小到大依次枚举,在不改变答案的情况下,能加进来就加。

  但我想错的地方是:如果第 i 个可以在某个最优解的情况下就加入它(即判断[1,n])。但这样最后得到的可能并不是一组合法解。

  所以用set维护前驱后继,判断[l,r]这一段才可以……

 

P.S.BZOJ200题留念

  1 /**************************************************************
  2     Problem: 1178
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:4008 ms
  7     Memory:41124 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 1178
 11 #include<set>
 12 #include<vector>
 13 #include<cstdio>
 14 #include<cstdlib>
 15 #include<cstring>
 16 #include<iostream>
 17 #include<algorithm>
 18 #define rep(i,n) for(int i=0;i<n;++i)
 19 #define F(i,j,n) for(int i=j;i<=n;++i)
 20 #define D(i,j,n) for(int i=j;i>=n;--i)
 21 #define pb push_back
 22 using namespace std;
 23  
 24 int getint(){
 25     int v=0,sign=1; char ch=getchar();
 26     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
 27     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
 28     return v*sign;
 29 }
 30 typedef long long LL;
 31 const int maxn=200010;
 32 #define debug
 33 /*******************template********************/
 34 struct rec{int x,y,z;}a[maxn],b[maxn],c[maxn],L,R;
 35 set<rec> s;
 36 set<rec> :: iterator itl,itr;
 37 bool cmp1(rec a,rec b){
 38     return a.x<b.x || (a.x==b.x && a.y>b.y);
 39 }
 40 bool cmp2(rec a,rec b){
 41     return a.z<b.z;
 42 }
 43 bool operator < (rec a,rec b){return a.x<b.x;}
 44 int A[maxn*2],B[maxn*2],d[maxn*2][19],n,m,N,M,ans;
 45  
 46 void ready(){
 47     sort(B+1,B+M+1);
 48     N=unique(B+1,B+M+1)-B-1;
 49     F(i,1,m){
 50         b[i].x=lower_bound(B+1,B+N+1,b[i].x)-B;
 51         b[i].y=lower_bound(B+1,B+N+1,b[i].y)-B;
 52     }
 53     sort(b+1,b+m+1,cmp1);
 54     int j=0x3f3f3f3f;
 55     D(i,m,1) if (b[i].y<j) j=b[i].y,a[++n]=b[i];
 56     F(i,1,n) c[i]=a[n-i+1];
 57     memcpy(a,c,sizeof(c));
 58     memset(d,0x3f,sizeof(d));
 59     j=n;
 60     D(i,N,1){
 61         d[i][0]=d[i+1][0];
 62         if (a[j].x==i) d[i][0]=min(d[i][0],a[j].y);
 63         F(k,1,17) if (d[i][k-1]!=0x3f3f3f3f) d[i][k]=d[d[i][k-1]+1][k-1];
 64         for(;j&&a[j].x==i;j--);
 65     }
 66 }
 67 int calc(int l,int r){
 68     int ans=0;
 69     D(i,17,0) if (d[l][i]<=r) l=d[l][i]+1,ans+=1<<i;
 70     return ans;
 71 }
 72  
 73 int main(){
 74 #ifndef ONLINE_JUDGE
 75     freopen("input.txt","r",stdin);
 76 #endif
 77     m=getint();
 78     F(i,1,m){
 79         B[++M]=b[i].x=getint();
 80         B[++M]=b[i].y=getint();
 81         b[i].z=i;
 82     }
 83     ready();
 84     printf("%d\n",calc(1,N));
 85     memcpy(a,b,sizeof(b));
 86     sort(a+1,a+m+1,cmp2);
 87     L.x=0,L.y=2,R.x=N+1,R.y=1;
 88     s.insert(L); s.insert(R);
 89     int l,r;
 90     F(i,1,m){
 91         L.x=a[i].x,L.y=1,R.x=a[i].y,R.y=2;
 92         itl=s.lower_bound(L);
 93         itr=s.upper_bound(R);
 94         if (itl!=itr||itr->y==2) continue;
 95         itl--; l=itl->x+1; r=itr->x-1;
 96         if (calc(l,a[i].x-1)+calc(a[i].y+1,r)+1!=calc(l,r)) continue;
 97         s.insert(L); s.insert(R);
 98         printf("%d ",a[i].z);
 99     }
100     return 0;
101 }
View Code

1178: [Apio2009]CONVENTION会议中心

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 512  Solved: 192
[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的整数。

Output

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

Sample Input

4
4 9
9 11
13 19
10 17

Sample Output

2
1 3

HINT

对于50%的输入,N≤3000。在所有输入中,N≤200000 请注意使用Readln读入数据........

Source

[Submit][Status][Discuss]
posted @ 2015-05-02 13:22  Tunix  阅读(801)  评论(0编辑  收藏  举报