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 }