【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 }
1178: [Apio2009]CONVENTION会议中心
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 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 9
9 11
13 19
10 17
Sample Output
1 3
HINT
对于50%的输入,N≤3000。在所有输入中,N≤200000 请注意使用Readln读入数据........