题目描述
逛逛集市,兑兑奖品,看看节目对农夫约翰来说不算什么,可是他的奶牛们非常缺乏锻炼——如果要逛完一整天的集市,他们一定会筋疲力尽的。所以为了让奶牛们也能愉快地逛集市,约翰准备让奶牛们在集市上以车代步。但是,约翰木有钱,他租来的班车只能在集市上沿直线跑一次,而且只能停靠\(N(1 ≤N≤20000)\)个地点(所有地点都以\(1\)到\(N\)之间的一个数字来表示)。现在奶牛们分成\(K(1≤K≤50000)\)个小组,第i 组有\(M_i(1 ≤M_i≤N)\)头奶牛,他们希望从\(S_i\)跑到\(T_i(1 ≤S_i<T_i≤N)\)。
由于班车容量有限,可能载不下所有想乘车的奶牛们,此时也允许小里的一部分奶牛分开乘坐班车。约翰经过调查得知班车的容量是\(C(1≤C≤100)\),请你帮助约翰计划一个尽可能满足更多奶牛愿望的方案。
输入输出格式
输入格式:
【输入】
第一行:包括三个整数:\(K\),\(N\)和\(C\),彼此用空格隔开。
第二行到\(K+1\)行:在第\(i+1\)行,将会告诉你第\(i\)组奶牛的信息:\(S_i\),\(E_i\)和\(M_i\),彼
此用空格隔开。
输出格式:
【输出】
第一行:可以坐班车的奶牛的最大头数。
输入输出样例
输入样例#1:
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:
10
说明
【样例说明】
班车可以把\(2\)头奶牛从\(1\)送到\(5\),\(3\)头奶牛从\(5\)送到\(8\),\(2\)头奶牛从\(8\)送到\(14\),\(1\)头奶牛从\(9\)送到\(12\),\(1\)头奶牛从\(13\)送到\(14\),\(1\)头奶牛从\(14\)送到\(15\)。
思路:
题意是给你几堆奶牛,每个奶牛都有想去的地方,给你一个汽车,汽车有一个容量和固定的行走路线,询问最多能搭载的奶牛的数量。
我们来考虑一种贪心的思想,按右端点从小到大排一遍序,为什么呢?后面说,然后对排好序的每堆奶牛依次进行遍历,如果当前有空位,空位大于这堆奶牛的数量,那就全上去,不然的话,就能上去几个就上去几个。这样下来的话,结果一定是最优的,其正确性不难证明,因为刚开始我们对每堆奶牛要到的地方从小到大排了序(即终点),那么每个位置最多只有一次奶牛上车,而且这些奶牛来自同一群,所以我们对每堆奶牛分别进行考虑即可,这就是为什么要按右端点排序的原因。贪心过程中,要维护最大值。因为要算最少的空位子,下面给出两种代码:
1、纯贪心&贪心:
#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 50007
using namespace std;
int ans,n,m,k,w[maxn];
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int u,v,c;
}e[maxn];
const int inf=0x7fffffff;
inline bool cmp(node a, node b) {
if(a.v!=b.v) return a.v<b.v;
return a.u<b.u;
}
int main() {
k=qread(),n=qread(),m=qread();
for(int i=1;i<=k;++i) e[i].u=qread(),e[i].v=qread(),e[i].c=qread();
sort(e+1,e+1+k,cmp);
for(int i=1;i<=k;++i) {
if(w[e[i].u]>=m) continue;
int minn=inf;
for(int j=e[i].u;j<=e[i].v;++j) {
minn=min(m-w[j],minn);
if(minn<=0) break;
}
if(minn>0) {
if(minn>=e[i].c) {
for(int j=e[i].u;j<e[i].v;++j)
w[j]+=e[i].c;
ans+=e[i].c;
}
else {
for(int j=e[i].u;j<e[i].v;++j)
w[j]+=minn;
ans+=minn;
}
}
}
printf("%d\n",ans);
return 0;
}
2、线段树&贪心&排序:
#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 20007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int inf=0x7fffffff;
int n,k,m,maxx[maxn<<2],lazy[maxn<<2],zrj,w[50007];
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int u,v,c;
}e[50007];
inline bool cmp(node a, node b) {
if(a.v!=b.v) return a.v<b.v;
return a.u<b.u;
}
inline void pushup(int rt) {
maxx[rt]=max(maxx[ls],maxx[rs]);
}
inline void pushdown(int rt) {
if(lazy[rt]) {
maxx[ls]+=lazy[rt],lazy[ls]+=lazy[rt];
maxx[rs]+=lazy[rt],lazy[rs]+=lazy[rt];
lazy[rt]=0;
}
}
void modify(int rt, int l, int r, int L, int R, int val) {
if(L>r||R<l) return;
if(L<=l&&r<=R) {
lazy[rt]+=val,maxx[rt]+=val;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
pushup(rt);
}
int cmax(int rt, int l, int r, int L, int R) {
if(L>r||R<l) return -inf;
if(L<=l&&r<=R) return maxx[rt];
int mid=(l+r)>>1,ans=-inf;
pushdown(rt);
if(L<=mid) ans=max(ans,cmax(ls,l,mid,L,R));
if(R>mid) ans=max(ans,cmax(rs,mid+1,r,L,R));
return ans;
}
int main() {
k=qread(),n=qread(),m=qread();
for(int i=1;i<=k;++i) e[i].u=qread(),e[i].v=qread(),e[i].c=qread();
sort(e+1,e+1+k,cmp);
for(int i=1;i<=k;++i) {
int p=cmax(1,1,n,e[i].u,e[i].v-1);
int minn=min(m-p,e[i].c);
zrj+=minn,w[i]+=minn;
modify(1,1,n,e[i].u,e[i].v-1,w[i]);
}
printf("%d\n",zrj);
return 0;
}