0%

1626.无矛盾的最佳球队

1626.无矛盾的最佳球队

题目描述:

一支球队,长度为 $ n $ ,每个球员有 $ score[i],age[i] $ 。如果年龄较小的球员的分数严格大于一名年龄较大的球员,则存在矛盾。同龄没有矛盾。返回可能的无矛盾球队中得分最高的分数。

数据范围:
$ 1\le n \le 1000,1\le scores[i] \le 10^6,1\le ages[i] \le 1000 $

题解:

很容易想到使用动态规划解决,设计状态 $ dp[i] $ 表示选择 $ i $ 号球员时能得到的最大分数。首先排序,按照年龄或者按照分数(这里先按照年龄排序)。这样的话可以得到递推方程

可以发现 $ dp[i] $ 的值只与当前值和 $ [0, scores[i]] $ 区间中分数的最大值有关。所以可以使用序列数据结构维护该区间最值(使用线段树或者树状数组)。由于 $ scores $ 的数据范围大一些,所以可以考虑维护 $ age $ 。也可以考虑离散化 $ scores $ 。

按照分数排序,得到新的对偶的方程

这样的话只需要维护 $ age $ 就行了。试试树状数组,线段树写的太多了。

类似线段树优化dp的题目:

Problem - 4521 (hdu.edu.cn)

B-卡牌对战游戏_华为杯中国地质大学(武汉)第十七届ICPC程序设计大赛暨 华中地区部分高校第十五届ICPC邀请赛竞赛 (nowcoder.com)

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const static int INF = 0x3f3f3f3f;
int bestTeamScore(vector<int> &scores, vector<int> &ages)
{
int n = scores.size();
vector<pair<int, int>> a;
vector<int> dp(n, 0);
for (int i = 0; i < n; ++i)
{
a.push_back({ages[i], scores[i]});
}
sort(a.begin(), a.end());
dp[0] = a[0].second;
int ans = dp[0];
for (int i = 1; i < n; ++i)
{
dp[i] = a[i].second;
for (int j = 0; j < i; ++j)
{
if (a[i].second >= a[j].second)
{
dp[i] = max(dp[i], dp[j] + a[i].second);
}
}
ans = max(ans, dp[i]);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const static int INF = 0x3f3f3f3f;
vector<int> c;
int query(int pos)
{
int ans = 0;
while (pos >= 1)
{
ans = max(ans, c[pos]);
pos -= lowbit(pos);
}
return ans;
}
void add(int pos, int k, int n)
{
while (pos <= n)
{
c[pos] = max(c[pos], k);
pos += lowbit(pos);
}
}
int lowbit(int x)
{
return x & -x;
}
int bestTeamScore(vector<int> &scores, vector<int> &ages)
{
int n = scores.size();
vector<pair<int, int>> a;
vector<int> dp(n, 0);
int max_age = 0;
for (int i = 0; i < n; ++i)
{
a.push_back({scores[i], ages[i]});
max_age = max(ages[i], max_age);
}
c.resize(max_age + 1, 0);
sort(a.begin(), a.end());
int ans = 0;
for (int i = 0; i < n; ++i)
{
dp[i] = query(a[i].second) + a[i].first;
add(a[i].second, dp[i], max_age);
ans = max(ans, dp[i]);
}
return ans;
}
};