题目描述

给出\(N\)件单位时间任务,对于第\(i\)件任务,如果要完成该任务,需要占用\([S_i, T_i]\)间的某个时刻,且完成后会有\(V_i\)的收益。求最大收益。

澄清:一个时刻只能做一件任务,做一个任务也只需要一个时刻。

输入格式

第一行一个整数\(N\),表示可供选择的任务个数。

接下来的第二到第\(N+1\)行,每行三个数,其中第\(i+1\)行依次为\(S_i,T_i,V_i\)。

输出格式

输出最大收益

样例

样例输入1

2
1 1 1
1 1 2

样例输出1

2

样例输入2

3
1 1 5
2 2 3
1 2 4

样例输出2

9

样例输入3

6
1 2 10
2 3 10
3 4 10
4 5 10
1 1 5
5 5 6

样例输出3

46

数据范围

在所有数据中,\(N\leq5000,1\leq S_i\leq 10^8,1\leq V_i \leq 10^8\)。

题解

我又诈尸了。

来到中山纪中集训,省选组的题目第一天就这么神(集训队的题能不神么)……真是\(Orz\),咱全场几乎爆零成功垫底。

回到题目,直接说正解。考虑将任务的价值从大到小排序,假设我们已经安排好了前\(i-1\)个任务,其中要完成的任务集合是\(S\)。如果要完成第\(i\)个任务会导致原来处于\(S\)的任务中的一个无法完成,那么我们果断放弃第\(i\)个任务(因为如果换做完成\(i\),并没有腾出更多时间,但却丢失了更多价值),否则我们没有理由不完成\(i\)个任务。

那么我们只需要完成一步就好了,那就是判断将任务\(i\)加入集合\(S\)后是否能让所有任务都能找到时间做。这个东西我们可以用一个简单粗暴的方法,每次从任务\(i\)的起始时间开始找,如果这个时间没有被占领,那么占领,结束。否则找到占领该时间的任务,记作\(j\)。此时就存在一个选择,到底是让\(i\)去后面找时间还是让\(j\)找?显然,能拖得更久的任务去尝试更好,也就是结束时间更晚的那一个去找。就这样递归下去,直到不冲突或者超出任务的结束时间为止(超出了当然就得放弃任务了……)。每次最多遇到\(i-1\)次冲突(因为最多也只有\(i-1\)个任务),判断一次的复杂度是\(O(n)\)的。

这里有一个空间上的优化。其实有用的时间其实并不多,我们将他们记为“活跃点”。我们从每个任务的起始时间开始找,找到第一个空位,就将它加入“活跃点”,显然只考虑活跃点的情况下仍然可以达到最优,这样可以把空间也优化到\(O(n)\)(然而代价是时间复杂度有了离散化时的\(log\))。

\(Code:\)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 5005
#define ll long long
int n;
struct node
{
int s, t, v;
}S[N];
bool cmp1(node a, node b){return a.s < b.s;}
bool cmp2(node a, node b){return a.v > b.v;}
int data[N], plc[N];
int Find(int x, int p)
{
if (p > S[x].t)
return 0;
if (!plc[p])
{
plc[p] = x;
return 1;
}
if (S[plc[p]].t < S[x].t)
return Find(x, p + 1);
if (Find(plc[p], p + 1))
{
plc[p] = x;
return 1;
}
return 0;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d%d", &S[i].s, &S[i].t, &S[i].v);
sort(S + 1, S + n + 1, cmp1);
for (int i = 1; i <= n; i++)
data[i] = max(data[i - 1] + 1, S[i].s);
for (int i = 1; i <= n; i++)
{
S[i].s = lower_bound(data + 1, data + n + 1, S[i].s) - data;
S[i].t = upper_bound(data + 1, data + n + 1, S[i].t) - data - 1;
}
sort(S + 1, S + n + 1, cmp2);
ll ans = 0;
for (int i = 1; i <= n; i++)
if (Find(i, S[i].s))
ans += S[i].v;
printf("%lld\n", ans);
}

「中山纪中集训省选组D1T1」最大收益 贪心的更多相关文章

  1. 「中山纪中集训省选组D4T1」折射伤害 高斯消元

    题目描述 在一个游戏中有n个英雄,初始时每个英雄受到数值为ai的伤害,每个英雄都有一个技能"折射",即减少自己受到的伤害,并将这部分伤害分摊给其他人.对于每个折射关系,我们用数对\ ...

  2. 「中山纪中集训省选组D2T1」书堆 欧拉常数

    题目描述 蚂蚁是勤劳的动物,他们喜欢挑战极限.现在他们迎来了一个难题!蚂蚁居住在图书馆里,图书馆里有大量的书籍.书是形状大小质量都一样的矩形.蚂蚁要把这些书摆在水平桌子的边缘.蚂蚁喜欢整洁的布置,所以 ...

  3. 中山纪中集训Day5叒是测试(划淼)

    A组T1 矩阵游戏(game) 九校联考24OI__D1T1 问题描述 LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵.第一行的数字是1,2,…M,第二行的数字是M+1,M+2…2*M ...

  4. 中山纪中集训Day1测试(摸鱼)

    AT3 粉刷匠 Description 赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= = 现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍.赫克托有K桶颜色各不 ...

  5. 中山纪中集训Day4双是测试(划沝) 九校联考-DL24凉心模拟Day2

    A组T1 锻造 (forging) 1.1 题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现......自己连一个史莱姆 ...

  6. 中山纪中集训Day2又是测试(划水)

    A组T1 bzoj 2674 Attack Description chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜.现在,他要开始征服世界的旅途了.他的敌人有N 座城市和N 个太守 ...

  7. 纪中集训 Day 2

    今天(其实是昨天= =)早上起来发现好冷好冷啊= = 吃完饭就准备比赛了,好吧B组难度的题总有一道不知到怎么写QAQ 太弱了啊!!! 蒟蒻没人权啊QAQ 今天第4题不会写,在这里说说吧 题目的意思就是 ...

  8. 纪中集训 Day1

    今天早上起来吃饭,发现纪中伙食真的是太差了!!!什么都不热,早餐的面包还好,然后就迎来了美好的早晨= = 早上做一套题,T1T2果断秒,T3一看就是noi原题,还好看过题解会写,然后就愉快的码+Deb ...

  9. 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并

    洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...

随机推荐

  1. Python3 - 基础(运算符)

    Python3-运算符 举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符. 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算 ...

  2. Spring Security 3多用户登录实现之二 多登录界面展示

    作者 接前讲,首先针对一个多种用户类型的登录需求,需要先实现多种用户类型的登录界面的展示,Spring Security提供了这样一个接口来帮助我们实现多种用户类型的登录界面的展示,这个接口就是Aut ...

  3. fitnesse的安装

    最近项目组有个单独的功能模块需要写自动化,由于是测试接口,我本来是想用之前那个项目组使用的robot framework+python,但是呢,项目组领导觉得,目前项目开发语言是java,相应的自动化 ...

  4. Linux运维相关命令

    df 查看磁盘空间大小 df命令是linux系统以磁盘分区为单位查看文件系统,可以加上参数查看磁盘剩余空间信息,命令格式: df -hl 显示格式为: 文件系统              容量 已用  ...

  5. packr 方便的潜入静态资源文件到golang 二进制文件中

    类似的工具以前有介绍过statik,今天使用的工具是packr 也是很方便的golang tools 安装 go get -u github.com/gobuffalo/packr/packr 或者我 ...

  6. python学习笔记一: 《python3 input()函数》

    一.在学习之前需要先了解: 1.Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型,即把任何输入看作str. 2.input可以用作文本输入,如用户名,密码框 ...

  7. 【LA 3942】 Remember the word

    题意 给定一个字符串和若干个单词,询问能把字符串分解成这些单词的方案数.比如abcd ,有单词a,b,ab,cd:就可以分解成a+b+cd或者ab+cd. 分析 trie树—>DP 代码 (感谢 ...

  8. 用gmsh做前处理

    原视频下载地址:  https://pan.baidu.com/s/1i4Y9fbJ  密码: 7rkb

  9. HTTP与RPC(Thrift)

    什么是RPC 从网络协议来说,Http协议与Rpc同属于应用层, 他们的底层都是tcp协议. RPC(即Remote Procedure Call,远程过程调用)和HTTP(HyperText Tra ...

  10. Hadoop综合大作业总评

    作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3363 1.把python爬取的数据传到linux 2.把数据的逗号代替为  ...