P3827火车运输
时间限制 : - MS 空间限制 : 265536 KB
评测说明 : 1000ms
问题描述
ByteLand火车站(编号0)每天都要发往全国各地N列客运火车,编号1 N。第i列火车的目的地是编号Si的火 车站。 对任意车站X,都与X+1车站有铁轨直接相连,因此火车站可以看成数轴上的整数点,第i列火车可以停靠区 间[0, Si]中的各个站点。每列火车装载乘客的最大容量为Ci。 有M个人需要乘坐火车。已知每个人的乘车区间为[Li, Ri],即是说,在Li上车,在Ri下车。 由于火车的容量限制,请你求出最多有多少人的乘车需求可以得到满足。
输入格式
第1行:2个整数N和M。
接下来N行,每行2个整数Si和Ci,表示第i辆车的目的站和容量。
接下来M行,每行2个整数Li和Ri,表示第i个乘客的乘车区间。
输出格式
第1行:1个整数,表示最多有多少乘客的乘车需求可以满足
样例输入
1 3
10 2
1 5
3 7
4 9
样例输出
2
提示
1 ≤ N,M ≤ 10^5
1 ≤ Si,Ci ≤ 10^9
1 ≤ Li ≤ Ri ≤ 10^9
分析:废话不多说,相信仔细看过题的同学们一定想了各种方法。直接说正解,这个题是一个经典的贪心模型!一辆容量为c的火车看成c辆容量为1的火车。那么每一辆火车毫无疑问不存在同一区间有两个或以上的人在上面,即一辆火车在一个位置上面最多只能有一个人。那么现在来说怎么贪心。
首先把火车按区间右端点由大到小排序,乘客双关键字排序(右端点由大到小优先)。显然排序后第一辆火车管不到的人就只有自杀了!然后,我们讨论每一个人,代码中now是记的当前这个人可以乘坐的火车数,cnt[i]是当前讨论过的人中左端点位于i的人数。原则:如果有空的火车,他当然可以坐,也可以选择和其他左端点在他的右端点右边的人一起坐,这也就是代码中now加的那一坨。now>0即这个人可以坐,那他就坐。那么堆是用来干嘛的?维护一些人的左端点,考虑这样一个问题,对于拼车的问题,因为是按右端点由大到小排序,先讨论的右端点一定大,如果一个人的区间是另一个人的子区间,对于拼车问题,这个人明显更优于另一个人!维护通过堆来实现!
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
inline void _read(int &x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9')
{if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int n,m;
struct node{
int l,r;
};
node pass[500005];
bool cmp1(node a,node b){
if(a.r==b.r)return a.l>b.l;
else return a.r>b.r;
}
struct node2{
int x,v;
};
node2 train[500005];
bool cmp2(node2 a,node2 b){
return a.x>b.x;
}
int tot=0;
int app[400005];
int cnt[500005];
priority_queue<int,vector<int>,greater<int> > q;
int ans=0;
int main(){
int i,j,k;
cin>>n>>m;
for(i=1;i<=n;i++){
_read(train[i].x);
_read(train[i].v);
app[++tot]=train[i].x;
}
for(i=1;i<=m;i++){
_read(pass[i].l);
_read(pass[i].r);
app[++tot]=pass[i].l;
app[++tot]=pass[i].r;
}
sort(app+1,app+1+tot);
tot=unique(app+1,app+1+tot)-app-1;
sort(train+1,train+1+n,cmp2);
sort(pass+1,pass+1+m,cmp1);
for(i=1;i<=n;i++){
train[i].x=lower_bound(app+1,app+1+tot,train[i].x)-app;
}
for(i=1;i<=m;i++){
pass[i].l=lower_bound(app+1,app+1+tot,pass[i].l)-app;
pass[i].r=lower_bound(app+1,app+1+tot,pass[i].r)-app;
}
int now,last;
i=1;j=1;
last=pass[1].r;
now=0;
while(pass[i].r>train[1].x&&i<=m){
i++;
}
for(;i<=m;i++){
while(train[j].x>=pass[i].r&&j<=n){
now+=train[j].v;
j++;
}
while(last>pass[i].r){
last--;
now+=cnt[last];
}
if(now){
now--;
ans++;
cnt[pass[i].l]++;
q.push(pass[i].l);
}
else if(q.size()&&q.top()<pass[i].l){
int temp=q.top();
cnt[temp]--;
cnt[pass[i].l]++;
q.pop();
q.push(pass[i].l);
}
}
cout<<ans;
}