BZOJ 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle
1577: [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
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
思路:
贪心的选取上下车,线段树维护是否可以上车,贪心的正确性显然,代码如下
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define ls p<<1
#define rs p<<1|1
#define im int mid = (l + r) >> 1
using namespace std;
const int N = 20000;
const int inf = 0x3f3f3f3f;
int k,n,c;
int minn[N<<2],laz[N<<2];
int tmp,ans;
struct cow {
int s,t,m;
}e[N<<2];
bool cmp(const cow &a,const cow &b) {
return a.t==b.t?a.s>b.s:a.t<b.t;
}
void pushdown(int l,int r,int p,int s) {
minn[p]+=s;
laz[p]+=s;
}
void change(int l,int r,int p,int x,int y) {
if(x<=l&&r<=y) {
laz[p]+=tmp;
minn[p]+=tmp;
return ;
}
im;
if(laz[p]) {
pushdown(l,mid,ls,laz[p]);
pushdown(mid+1,r,rs,laz[p]);
laz[p]=0;
}
if(x<=mid)
change(l,mid,ls,x,y);
if(y>mid)
change(mid+1,r,rs,x,y);
minn[p]=max(minn[ls],minn[rs]);
}
void query(int l,int r,int p,int x,int y) {
if(x<=l&&r<=y) {
tmp=max(tmp,minn[p]);
return ;
}
im;
if(laz[p]) {
pushdown(l,mid,ls,laz[p]);
pushdown(mid+1,r,rs,laz[p]);
laz[p]=0;
}
if(x<=mid)
query(l,mid,ls,x,y);
if(y>mid)
query(mid+1,r,rs,x,y);
}
int main() {
scanf("%d%d%d",&k,&n,&c);
for(int i=1;i<=k;i++) {
scanf("%d%d%d",&e[i].s,&e[i].t,&e[i].m);
}
sort(e+1,e+k+1,cmp);
for(int i=1;i<=k;i++) {
int tm;
int s=e[i].s,t=e[i].t,m=e[i].m;
tmp = 0;
query(1,n,1,s,t-1);
//printf("%d::::",tmp);
if(tmp>=c)continue;
if(tmp+m<=c)tm=m;
else tm=c-tmp;
tmp=tm;
change(1,n,1,s,t-1);
ans += tm;
//printf("%d %d %d\n",s,t,tmp);
}
printf("%d\n",ans);
}
欢迎来原博客看看 >原文链接<

浙公网安备 33010602011771号