轻轨【线段树】【贪心】
题目大意:
有个站点的轻轨站,有一个容量为的列车起点在号站点,终点在号站点,有组牛群,每组数量为,行程起点和终点分别为和。请你计算最多有多少头牛可以搭乘轻轨。
思路:
线段树+贪心
其实这道题直接用贪心就能过,编程复杂度也简单,但是就是比较难理解。
这道题如果我们将每群牛的起点和终点看成起始时间和终止时间,看做会场场数,那么这道题就很像 活动安排 了。
每次查询起点和终点的之间的最大值,将牛尽量放进车上,并标记这个区间新添加了这么多牛,中间所有添加的牛的数量即为答案。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,k,sum,ans,sum2;
struct node1
{
int l,r,max,lazy;
}tree[300001];
struct node2
{
int l,r,num;
}a[300001];
void make(int x)
{
if (tree[x].r==tree[x].l) return;
int mid=(tree[x].l+tree[x].r)/2;
tree[x*2].l=tree[x].l;
tree[x*2].r=mid;
tree[x*2+1].l=mid+1;
tree[x*2+1].r=tree[x].r;
make(x*2);
make(x*2+1);
}
bool cmp(node2 x,node2 y)
{
return x.r<y.r||(x.r==y.r&&x.l<y.l);
}
void pushdown(int x)
{
if (tree[x].lazy)
{
tree[x*2].lazy+=tree[x].lazy;
tree[x*2+1].lazy+=tree[x].lazy;
tree[x*2].max+=tree[x].lazy;
tree[x*2+1].max+=tree[x].lazy;
tree[x].lazy=0;
}
}
int find(int x,int l,int r)
{
if (tree[x].l>r||tree[x].r<l) return 0;
if (tree[x].l>=l&&tree[x].l<=r) return tree[x].max;
pushdown(x);
int lmax=find(x*2,l,r);
int rmax=find(x*2+1,l,r);
tree[x].max=max(tree[x*2].max,tree[x*2+1].max);
int maxn=max(lmax,rmax);
return maxn;
}
void add(int x,int l,int r,int k)
{
if (tree[x].l>r||tree[x].r<l) return;
if (tree[x].l>=l&&tree[x].r<=r)
{
tree[x].max+=k;
tree[x].lazy+=k;
return;
}
pushdown(x);
add(x*2,l,r,k);
add(x*2+1,l,r,k);
tree[x].max=max(tree[x*2].max,tree[x*2+1].max);
}
int main()
{
scanf("%d%d%d",&m,&n,&k);
tree[1].l=1;
tree[1].r=n;
make(1);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].num);
}
sort(a+1,a+1+m,cmp);
for (int i=1;i<=m;i++)
{
sum=find(1,a[i].l,a[i].r);
if (k<sum) continue;
sum2=min(a[i].num,k-sum);
ans+=sum2;
add(1,a[i].l,a[i].r-1,sum2);
}
return printf("%d\n",ans)&0;
}