codeforces Gym 101341 K Competitions
来源:互联网 发布:孕囊后两个数据一样 编辑:程序博客网 时间:2024/05/19 15:22
Problem
codeforces.com/gym/101341/problem/K
vjudge.net/contest/162325#problem/K
Meaning
有 n 场比赛,每一场有:开始时间 a、结束时间 b、价值 c。问在这 n 场中挑选若干场,在使得总的价值最大的前提下,总的时长最短,要求任意两场比赛时间不能有重叠的部分(不算边界)。输出比赛场数、总价值、总时长、所选比赛编号。
Analysis
差不多就是《挑战程序设计竞赛(2e)》第 246 页的那题,虽然那题是网络流,但后面也有提这题的解法。
定义状态:
dp[i]:在时间 [ 0 , i ] 内能得到的最大价值;
len[i]:在得到上述最大价值的情况下的最短时长。
状态转移:用结束时间就是 i 的那些比赛来更新 dp[i]
dp[i] = max { dp[i-1] , dp[ a[j] ] + c[j] | 1 <=j <= n , b[j] = i } (j 表示第 j 个比赛,a、b、c 的意义同题目描述)
如果在 j 点更新了 dp[i],就有:len[i] = len[ a[j] ] + ( b[j] - a[j] );
若选 j 点得到与 dp[i] 一样的值,但能有更短时间,也要更新 len[i]。
时间范围很大,要进行离散化。
还要用个数组记录下当前时刻 i 选的是哪场比赛,好记录路经。
Code
#include <cstdio>#include <algorithm>#include <stack>using namespace std;const int N = 200000;struct node{int a, b, c;int l; // length = b - aint id; // 比赛编号,因为要排序,不能直接用下标表示编号node() {}node(int _b): b(_b) {}bool operator < (const node &rhs) const{return b < rhs.b;}} com[N];int ab[N<<1]; // 离散化数组int which[N<<1|1]; // 时刻i所选的比赛,记的是下标而不是编号long long dp[N<<1|1], len[N<<1|1];stack<int> stk;int main(){int n;scanf("%d", &n);int top = 0;for(int i=0; i<n; ++i){scanf("%d%d%d", &com[i].a, &com[i].b, &com[i].c);com[i].l = com[i].b - com[i].a;com[i].id = i + 1;ab[top++] = com[i].a;ab[top++] = com[i].b;}/* 离散化时刻 */sort(ab, ab + top);top = unique(ab, ab + top) - ab;for(int i=0; i<n; ++i){com[i].a = lower_bound(ab, ab+top, com[i].a) - ab + 1;com[i].b = lower_bound(ab, ab+top, com[i].b) - ab + 1;}/* 按结束时间排序,可二分找到结束时间为i的那些比赛 */sort(com, com + n);dp[0] = len[0] = 0;which[0] = -1;for(int i=1; i<=top; ++i){dp[i] = dp[i-1];len[i] = len[i-1];which[i] = which[i-1];int beg = lower_bound(com, com+n, node(i)) - com;for(int j=beg; j<n && com[j].b==i; ++j)if(dp[i] < dp[com[j].a] + com[j].c){dp[i] = dp[com[j].a] + com[j].c;len[i] = len[com[j].a] + com[j].l;which[i] = j;}else if(dp[i] == dp[com[j].a] + com[j].c &&len[i] > len[com[j].a] + com[j].l){len[i] = len[com[j].a] + com[j].l;which[i] = j;}}for(int i=top; ~which[i]; i=com[which[i]].a)stk.push(com[which[i]].id);printf("%d %I64d %I64d\n", stk.size(), dp[top], len[top]);for( ; stk.size(); stk.pop())printf("%d%c", stk.top(), stk.size()==1?'\n':' ');return 0;}
0 0
- codeforces Gym 101341 K Competitions
- codeforces [Gym-100814K]
- Codeforces gym 101149 K 想法
- Codeforces gym 101102 K 想法
- 【codeforces 765A】Neverending competitions
- Codeforces Gym 100792K King's Rout
- Codeforces Gym 101142 K. King's Heir
- Codeforces Gym 101484 K Counting Good Teams
- Codeforces Gym 100623K Problem K. Key to Success
- A. Neverending competitions Codeforces Round #397
- [杂题] Codeforces Gym 101190 NEERC 16 K. Kids Designing Kids
- Codeforces Gym 101173 K. Key Knocking (构造)
- Codeforces Gym 101164 K. Cutting (字符串 HASH)
- Codeforces Gym 101174 K. Balls and Needles (DFS)
- 【Codeforces Gym
- 【codeforces Gym
- codeforces Gym
- codeforces Gym
- android数据库
- SDL2 Qt Mingw编译
- 关于Oracle函数LPAD、RPAD及ROUND的使用
- 给Domino插上连接池的翅膀(一)--JnpServer实现
- HDU折线分割平面
- codeforces Gym 101341 K Competitions
- python的内存管理机制
- xcode 中#pragma得使用
- cocos
- 关于hashcode 里面 使用31 系数的问题
- $("#.form").serialisable();
- git clone慢的问题
- 微信小程序KFC
- 跟对人做对事,日入千元不是梦