noip模拟赛 公交车

题目描述
LYK在玩一个游戏。
有k群小怪兽想乘坐公交车。第i群小怪兽想从xi出发乘坐公交车到yi。但公交车的容量只有M,而且这辆公交车只会从1号点行驶到n号点。
LYK想让小怪兽们尽可能的到达自己想去的地方。它想知道最多能满足多少小怪兽的要求。
当然一群小怪兽没必要一起上下车,它们是可以被分开来的。

输入格式(bus.in)
第一行三个数k,n,M。
接下来k行每行3个数xi,yi和ci。其中ci表示第i群小怪兽的小怪兽数量。

输出格式(bus.out)
一个数表示最多有多少只小怪兽能满足要求。

输入样例
3 5 3
1 3 4
3 5 2
1 5 3

输出样例
5

样例解释
第一群的3只小怪兽在1号点上车,并在3号点下车。
第二群的2只小怪兽在3号点上车,5号点下车。

数据范围
对于30%的数据小怪兽的总数不超过10只,n<=10。
对于另外30%的数据k,n<=1000。
对于100%的数据1<=n<=20000,1<=k<=50000,1<=M<=100,1<=ci<=100,1<=xi<yi<=n。

分析:把一群小怪兽看做一条有权值的线段,那么就把题目转化为了覆盖尽量多的线段,使他们尽量不想交,这就是一类经典的贪心问题了.

      先把所有的线段按照右端点排序,用一个数组f记录第i个时刻车上已经有多少人了,因为是按照右端点排序的,所以每次加满人一定是最优的,因为加人是影响到后面的操作的,已经按照右端点排序了,所以对后面的影响最小,那么查询一下[x,y]中最多有多少人,然后把能放上的人全部放上去.

      涉及到区间求最大值和区间修改,可以用线段树来优化.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int k, n, m, maxx[200010], tag[200010], ans;

struct node
{
    int x, y, c;
}e[50010];

void pushup(int o)
{
    maxx[o] = max(maxx[o * 2], maxx[o * 2 + 1]);
}

bool cmp(node a, node b)
{
    if (a.y == b.y)
        return a.x > b.x;
    return a.y < b.y;
}

void pushdown(int o)
{
    if (tag[o])
    {
        tag[o * 2] += tag[o];
        tag[o * 2 + 1] += tag[o];
        maxx[o * 2] += tag[o];
        maxx[o * 2 + 1] += tag[o];
        tag[o] = 0;
    }
}

void update(int o, int l, int r, int x, int y, int v)
{
    if (x <= l && r <= y)
    {
        tag[o] += v;
        maxx[o] += v;
        return;
    }
    pushdown(o);
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(o * 2, l, mid, x, y, v);
    if (y > mid)
        update(o * 2 + 1, mid + 1, r, x, y, v);
    pushup(o);
}

int query(int o, int l, int r, int x, int y)
{
    if (x <= l && r <= y)
        return maxx[o]; 
    pushdown(o);
    int mid = (l + r) >> 1, res = 0;
    if (x <= mid)
        res = max(res, query(o * 2, l, mid, x, y));
    if (y > mid)
        res = max(res, query(o * 2 + 1, mid + 1, r, x, y)); 
    return res;
}

int main()
{
    scanf("%d%d%d", &k, &n, &m);
    for (int i = 1; i <= k; i++)
        scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].c);
    sort(e + 1, e + 1 + k, cmp);
    for (int i = 1; i <= k; i++)
    {
        int temp = query(1, 1, n, e[i].x, e[i].y), res = 0;
        if (temp >= m)
            continue;
        if (temp + e[i].c <= m)
            res = e[i].c;
        else
            res = m - temp;
        ans += res;
        update(1, 1, n, e[i].x, e[i].y - 1, res);
    }
    printf("%d\n", ans);

    return 0;
}

 

posted @ 2017-10-17 18:19  zbtrs  阅读(315)  评论(0编辑  收藏  举报