1577: [Usaco2009 Feb]庙会捷运Fair Shuttle
Time Limit: 10 Sec
Memory Limit: 64 MB
Submit: 310
Solved: 171
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
HINT
捷运可以把2头奶牛从展台1送到展台5,3头奶牛从展台5到展台8, 2头奶牛从展台8 到展台14,1头奶牛从展台9送到展台12,一头奶牛从展台13送到展台14, 一头奶牛从 14送到15。
题解:
先贪心:
把询问按照右端点的大小递增排序,然后右端点相同时,左端点较大的在前
然后上线段树:
对于每一个区间,查询最小值,在最小值和该团队的牛的数量取一个min,之后把区间减去min,也就是上尽可能多的牛
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005;
struct pp {int l,r,w;} Q[N];
struct Tree{int l,r,mn,lazy;}T[N*4];
int n,l,c,ans;
bool cmp(pp u,pp v)
{
if(u.r!=v.r) return u.r<v.r;
return u.l>v.l;
}
void pushup(int x)
{
T[x].mn=min(T[x<<1].mn,T[x<<1|1].mn);
}
void build(int x,int l,int r)
{
T[x].l=l,T[x].r=r;
T[x].mn=c;
if(l==r) return;
int mid=(T[x].l+T[x].r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void pushdown(int x)
{
int lc=x<<1,rc=x<<1|1;
T[lc].mn+=T[x].lazy;
T[rc].mn+=T[x].lazy;
T[lc].lazy+=T[x].lazy;
T[rc].lazy+=T[x].lazy;
T[x].lazy=0;
}
int Query(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r) return T[x].mn;
if(T[x].lazy) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) return Query(x<<1,l,r);
else if(l>mid) return Query(x<<1|1,l,r);
else return min(Query(x<<1,l,mid),Query(x<<1|1,mid+1,r));
}
void Modify(int x,int l,int r,int v)
{
if(T[x].l==l&&T[x].r==r)
{
T[x].mn+=v;
T[x].lazy+=v;
return;
}
if(T[x].lazy) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) Modify(x<<1,l,r,v);
else if(l>mid) Modify(x<<1|1,l,r,v);
else Modify(x<<1,l,mid,v),Modify(x<<1|1,mid+1,r,v);
pushup(x);
}
int main()
{
scanf("%d%d%d",&n,&l,&c);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].w);
Q[i].r--;
}
sort(Q+1,Q+n+1,cmp);
build(1,1,l);
for(int i=1;i<=n;i++)
{
int x=Q[i].l,y=Q[i].r;
int tmp=min(Q[i].w,Query(1,x,y));
if(tmp)
{
ans+=tmp;
Modify(1,x,y,-tmp);
}
}
printf("%d",ans);
}
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005;
struct pp {int l,r,w;} Q[N];
struct Tree{int l,r,mn,lazy;}T[N*4];
int n,l,c,ans;
bool cmp(pp u,pp v)
{
if(u.r!=v.r) return u.r<v.r;
return u.l>v.l;
}
void pushup(int x)
{
T[x].mn=min(T[x<<1].mn,T[x<<1|1].mn);
}
void build(int x,int l,int r)
{
T[x].l=l,T[x].r=r;
T[x].mn=c;
if(l==r) return;
int mid=(T[x].l+T[x].r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void pushdown(int x)
{
int lc=x<<1,rc=x<<1|1;
T[lc].mn+=T[x].lazy;
T[rc].mn+=T[x].lazy;
T[lc].lazy+=T[x].lazy;
T[rc].lazy+=T[x].lazy;
T[x].lazy=0;
}
int Query(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r) return T[x].mn;
if(T[x].lazy) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) return Query(x<<1,l,r);
else if(l>mid) return Query(x<<1|1,l,r);
else return min(Query(x<<1,l,mid),Query(x<<1|1,mid+1,r));
}
void Modify(int x,int l,int r,int v)
{
if(T[x].l==l&&T[x].r==r)
{
T[x].mn+=v;
T[x].lazy+=v;
return;
}
if(T[x].lazy) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) Modify(x<<1,l,r,v);
else if(l>mid) Modify(x<<1|1,l,r,v);
else Modify(x<<1,l,mid,v),Modify(x<<1|1,mid+1,r,v);
pushup(x);
}
int main()
{
scanf("%d%d%d",&n,&l,&c);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].w);
Q[i].r--;
}
sort(Q+1,Q+n+1,cmp);
build(1,1,l);
for(int i=1;i<=n;i++)
{
int x=Q[i].l,y=Q[i].r;
int tmp=min(Q[i].w,Query(1,x,y));
if(tmp)
{
ans+=tmp;
Modify(1,x,y,-tmp);
}
}
printf("%d",ans);
}