题面:Luogu2255
显然是一个贪心嘛。。。慢慢分析
摄像机台数=1
这种情况,在当前时间我们只要找开始时间大于等于当前时间,结束时间尽量小的节目,这样才能留出更多时间拍后面的节目,所以排个序找一下就好了
摄像机台数=2
这种情况嘛。。。上面那个贪心就不对了,反例可以自己找一个(很好想的)
但是按照这个思想是可以的,我们其实可以找当前空闲的摄像机拍是吧
有几种情况:
- 两台摄像机都在拍摄其他节目,这个时候显然不行
- 有一台摄像机空闲,那就选这台继续拍下去
- 两台都空闲,找两者结束之前拍摄较晚的继续拍下去,另外一台留给后面的拍,这样选择余地更多(浪费也少)
然后这题就可以做了,不过还有一个强化版。。。
强化版:摄像机台数<=n、记录方案
(我们的某毒瘤模拟赛搞出来的)
思路倒是也差不多,也是按照这样的选法贪心下去就可以了
按照原题数据范围也过了的
不过这样找摄像机的时间花费太多。。。我们可以把题目再强化一下,n<=100000
这样暴力找就GG,不过这个东西是可以用平衡树维护的
但是平衡树太麻烦了,STL的multiset就可以维护
至于记录方案,可以在选择摄像机的时候把选的节目记录下来,vector和链表都是可以的
上强化版代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdlib>
#include<string>
#include<ctime>
#include<queue>
#include<set>
#include<climits>
#include<vector>
#define mp(i,j) make_pair(i,j)
using namespace std;
inline int read(){
int k=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}
return k*f;
}
multiset<pair<int,int> >s;
struct ppap{int l,r,x;}a[100001];
int n,m,ans=0;
vector<int>an[100001];
inline bool cmp(ppap a,ppap b){return a.r<b.r;}
int main()
{
n=read();m=read();//m即为摄像机台数,原题m改为2即可
for(int i=1;i<=n;i++)a[i].l=read(),a[i].r=read(),a[i].x=i;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=m;i++)s.insert(mp(0,i));
multiset<pair<int,int> >::iterator p;//迭代器
for(int i=1;i<=n;i++){
p=s.upper_bound(mp(a[i].l,1e9));
if(p--!=s.begin()){
ans++;int q=p->second;
an[q].push_back(a[i].x);
s.erase(p);s.insert(mp(a[i].r,q));
}
}
printf("%d\n",ans);
for(int i=1;i<=m;i++){
int p=an[i].size();printf("%d ",p);
for(int j=0;j<p;j++)printf("%d ",an[i][j]);
puts("");
}//原题方案不用输出哦
return 0;
}