bzoj1651 / P2859 [USACO06FEB]摊位预订Stall Reservations

P2859 [USACO06FEB]摊位预订Stall Reservations

维护一个按右端点从小到大的优先队列

蓝后把数据按左端点从小到大排序,顺序枚举。

每次把比右端点比枚举线段左端点小的数据从优先队列中删掉。

在整个过程中队列的最大长度即为答案。

总之用优先队列模拟一下就ok了

对于luogu需要输出方案数的问题:

再开一个优先队列存未用的编号

每次有线段进队时取走最小的编号,出队时再还回来。

似乎暴力也行(大雾)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<algorithm>
 6 using namespace std;
 7 int max(int a,int b){return a>b?a:b;}
 8 #define N 50005
 9 struct data{
10     int l,r,id;
11     void init(int x){scanf("%d%d",&l,&r);id=x;}
12     bool operator < (const data &tmp) const{
13         return r>tmp.r;
14     }
15 }a[N]; priority_queue <data> h;
16 priority_queue <int,vector<int>,greater<int> > d;
17 bool cmp(const data &A,const data &B){return A.l<B.l;}
18 int n,mp[N],ans;
19 int main(){
20     scanf("%d",&n);
21     for(int i=1;i<=n;++i) a[i].init(i),d.push(i);
22     sort(a+1,a+n+1,cmp);
23     for(int i=1;i<=n;++i){
24         if(!h.empty()){
25             for(data q=h.top();!h.empty();q=h.top()){
26                 if(q.r>=a[i].l) break;
27                 d.push(mp[q.id]);h.pop();
28             }
29         }h.push(a[i]);
30         mp[a[i].id]=d.top(); d.pop();
31         ans=max(ans,h.size());
32     }printf("%d\n",ans);
33     for(int i=1;i<=n;++i) printf("%d\n",mp[i]);
34     return 0;
35 }
View Code

 

posted @ 2018-12-05 15:06  kafuuchino  阅读(139)  评论(0编辑  收藏  举报