线段树火车运输

ByteLand火车站(编号0)每天都要发往全国各地N列客运火车,编号1 N。第i列火车的目的地是编号Si的火车站。
对任意车站X,都与X+1车站有铁轨直接相连,因此火车站可以看成数轴上的整数点,第i列火车可以停靠区间[0, Si]中的各个站点。每列火车装载乘客的最大容量为Ci。
有M个人需要乘坐火车。已知每个人的乘车区间为[Li, Ri],即是说,在Li上车,在Ri下车。由于火车的容量限制,请你求出最多有多少人的乘车需求可以得到满足。

贪心+线段树

很明显这个题存在贪心的可能性

而很明显人和火车是一条线段

这个时候按照左端点排序即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
#define lc (p<<1)
#define rc (p<<1|1)
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
struct Node{
	int s,c;
}A[N];
struct Person{
	int l,r;
}B[N];
multiset<int> S;
int n,m;
bool cmp(Person A,Person B){
	if(B.l<=A.l&&A.r<=B.r)return 1;
	else if(A.l<=B.l&&B.r<=A.r)return 0;
	else return A.l<B.l;
}
int mmp[N<<2];
struct Segment_Tree{
	int lson,rson,sum,lazy;
}T[N<<2];
inline void PushUp(int p){
	T[p].sum=min(T[lc].sum,T[rc].sum);	
}
inline void PushDown(int p){
	if(T[p].lazy){
		T[lc].sum+=T[p].lazy;
		T[rc].sum+=T[p].lazy;
		T[lc].lazy+=T[p].lazy;
		T[rc].lazy+=T[p].lazy;
		T[p].lazy=0;
	}
}
inline void Build(int p,int l,int r){
	T[p].lson=l;
	T[p].rson=r;
	T[p].lazy=0;
	T[p].sum=0;
	if(l==r){
		return;
	}
	int mid=(l+r)>>1;
	Build(lc,l,mid);
	Build(rc,mid+1,r);
}
inline void Update(int p,int l,int r,int val){
	if(l<=T[p].lson&&T[p].rson<=r){
		T[p].sum+=val;
		T[p].lazy+=val;
		return;
	}
	PushDown(p);
	int mid=(T[p].lson+T[p].rson)>>1;
	if(l<=mid)Update(lc,l,r,val);
	if(mid <r)Update(rc,l,r,val);
	PushUp(p);
}
inline int Query(int p,int l,int r){
	if(l<=T[p].lson&&T[p].rson<=r){
		return T[p].sum;
	}
	PushDown(p);
	int mid=(T[p].lson+T[p].rson)>>1;
	int ret=1e7;
	if(l<=mid)ret=min(ret,Query(lc,l,r));
	if(mid< r)ret=min(ret,Query(rc,l,r));
	return ret;
}
int main(){
	read(n);
	read(m);
	for(int i=1;i<=n;++i){
		read(A[i].s);
		A[i].s-=1;
		mmp[++mmp[0]]=A[i].s;
		read(A[i].c);
	}
	for(int i=1;i<=m;++i){
		read(B[i].l);
		mmp[++mmp[0]]=B[i].l;
		read(B[i].r);
		B[i].r-=1;
		mmp[++mmp[0]]=B[i].r;
	}
	sort(mmp+1,mmp+1+mmp[0]);
	int len=unique(mmp+1,mmp+1+mmp[0])-mmp-1;
	for(int i=1;i<=n;++i){
		A[i].s=lower_bound(mmp+1,mmp+1+len,A[i].s)-mmp;
	}
	for(int i=1;i<=m;++i){
		B[i].l=lower_bound(mmp+1,mmp+1+len,B[i].l)-mmp;
		B[i].r=lower_bound(mmp+1,mmp+1+len,B[i].r)-mmp;
	}	
	sort(B+1,B+1+m,cmp);
	Build(1,1,len);
	for(int i=1;i<=n;++i){
		Update(1,1,A[i].s,A[i].c);
	}
	int ans=0;
	for(int i=1;i<=m;++i){
		int now=Query(1,B[i].l,B[i].r);
		if(now>0){
			ans++;
			Update(1,B[i].l,B[i].r,-1);
		}
	}
	cout<<ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值