[Usaco2009 Feb]庙会捷运Fair Shuttle

Description
公交车一共经过N(1<=N<=20000)个站点,从站点1一直驶到站点N。K(1<=K<=50000)群奶牛希望搭乘这辆公交车。第i群牛一共有Mi(1<=Mi<=N)只.

他们希望从Si到Ei去。
公交车只能座C(1<=C<=100)只奶牛。而且不走重复路线,请计算这辆车最多能满足多少奶牛听要求。
注意:对于每一群奶牛,可以部分满足,也可以全部满足,也可以全部不满足。

Input
第1行: 三个整数: K,N,C。 由空格隔开。

第2..K+1行:第i+1行,告诉你第i组奶牛的信息: S_i, E_i and M_i。由空格隔开。

Output
一行:可以在庙会乘坐捷运的牛的最大头数

Sample Input
8 15 3
1 5 2
13 14 1
5 8 3
8 14 2
14 15 1
9 12 1
12 15 2
4 6 1

Sample Output
10

HINT
公交车可以把2头奶牛从展台1送到展台5,3头奶牛从展台5到展台8, 2头奶牛从展台8 到展台14,1头奶牛从展台9送到展台12,一头奶牛从展台13送到展台14, 一头奶牛从 14送到15。


这个题目的贪心思想显而易见,我们肯定要让下车早的奶牛上车,其次就是上车晚的。然后如何判断能上多少奶牛呢?用线段树记录每个时间点,车上还有多少空位,然后大力维护一波就可以了

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())   x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x>=10) print(x/10);
	putchar(x%10+'0');
}
const int N=5e4,M=2e4;
int n,m,K;
int root=1;
struct AC{
	int l,r,val;
	void join(int x,int y,int z){l=x,r=y,val=z;}
	bool operator <(const AC &x)const{return r!=x.r?r<x.r:l>x.l;}
}A[N+10];
struct Tree{
	#define ls (p<<1)
	#define rs ((p<<1)|1)
	int Min[M*16+10],lazy[M*16+10];
	void updata(int p){Min[p]=min(Min[ls],Min[rs]);}
	void pushdown(int p){//“懒惰”标记
		if (!lazy[p])	return;
		lazy[ls]+=lazy[p];
		lazy[rs]+=lazy[p];
		Min[ls]+=lazy[p];
		Min[rs]+=lazy[p];
		lazy[p]=0;
	}
	void build(int p,int l,int r){
		if (l==r){Min[p]=K;return;}//开始空位为K
		int mid=(l+r)>>1;
		build(ls,l,mid),build(rs,mid+1,r);
		updata(p);
	}
	int get(int p,int l,int r,int x,int y){
		pushdown(p);
		if (x<=l&&r<=y)	return Min[p];
		int mid=(l+r)>>1,ans1=inf,ans2=inf;
		if (x<=mid)	ans1=get(ls,l,mid,x,y);
		if (y>mid)	ans2=get(rs,mid+1,r,x,y);
		if (ans1==inf&&ans2==inf)	return 0;
		return min(ans1,ans2);
	}
	void change(int p,int l,int r,int x,int y,int t){
		pushdown(p);
		if (x<=l&&r<=y){Min[p]+=t,lazy[p]+=t;return;}
		int mid=(l+r)>>1;
		if (x<=mid)	change(ls,l,mid,x,y,t);
		if (y>mid)	change(rs,mid+1,r,x,y,t);
		updata(p);
	}
}T;
int main(){
	n=read(),m=read(),K=read();
	int ans=0;
	for (int i=1,x,y,z;i<=n;i++)	x=read(),y=read()-1,z=read(),A[i].join(x,y,z);//因为在时刻r奶牛已经下车了,所以右端点要--
	sort(A+1,A+1+n);
	T.build(1,1,m);
	for (int i=1;i<=n;i++){
		int l=A[i].l,r=A[i].r;
		int tmp=min(A[i].val,T.get(1,1,m,l,r));//看看能上多少奶牛,上不了的就干脆别上了(不是vip不能挤上车)
		if (tmp)	T.change(1,1,m,l,r,-tmp),ans+=tmp;//更新,包括答案的更新和线段树的更新
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Wolfycz/p/8411123.html