49
49
50
50
<!-- 这里可写通用的实现逻辑 -->
51
51
52
- ** 方法一:动态规划**
52
+ ** 方法一:排序 + 动态规划**
53
53
54
- 最长上升子序列模型 。
54
+ 我们可以将球员按照分数从小到大排序,如果分数相同,则按照年龄从小到大排序 。
55
55
56
- 将所有球员先按照年龄从小到大排序(年龄相同,则按照分数从小到大排),然后在分数数组中求解最长上升子序列和的最大值即可。最长上升子序列朴素做法,时间复杂度 $O(n^2)$ 。
56
+ 接下来,使用动态规划求解 。
57
57
58
- 类似题型:洛谷 “[ P2782 友好城市] ( https://www.luogu.com.cn/problem/P2782 ) ”。
58
+ 我们定义 $f[ i] $ 表示以排序后的第 $i$ 个球员作为最后一个球员的最大得分,那么答案就是 $\max_ {0 \leq i < n} f[ i] $。
59
+
60
+ 对于 $f[ i] $,我们可以枚举 $0 \leq j \lt i$,如果第 $i$ 个球员的年龄大于等于第 $j$ 个球员的年龄,则 $f[ i] $ 可以从 $f[ j] $ 转移而来,转移方程为 $f[ i] = \max(f[ i] , f[ j] )$。然后我们将第 $i$ 个球员的分数加到 $f[ i] $ 中,即 $f[ i] += scores[ i] $。
61
+
62
+ 最后,我们返回 $\max_ {0 \leq i < n} f[ i] $ 即可。
63
+
64
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为球员的数量。
65
+
66
+ ** 方法二:排序 + 树状数组**
67
+
68
+ 与方法一类似,我们可以将球员按照分数从小到大排序,如果分数相同,则按照年龄从小到大排序。
69
+
70
+ 接下来,我们使用树状数组维护不超过当前球员年龄的球员的最大得分。每一次,我们只需要在 $O(\log m)$ 的时间内找出不超过当前球员年龄的球员的最大得分,然后将当前球员的分数加到该得分上,即可更新当前球员年龄的最大得分。
71
+
72
+ 最后,我们返回得分的最大值即可。
73
+
74
+ 时间复杂度 $O(n \times (\log n + \log m))$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别为球员的数量和球员的年龄的最大值。
59
75
60
76
<!-- tabs:start -->
61
77
66
82
``` python
67
83
class Solution :
68
84
def bestTeamScore (self , scores : List[int ], ages : List[int ]) -> int :
69
- nums = list (zip (ages, scores))
70
- nums.sort()
71
- n = len (nums)
72
- dp = [num[1 ] for num in nums]
73
- for i in range (n):
85
+ arr = sorted (zip (scores, ages))
86
+ n = len (arr)
87
+ f = [0 ] * n
88
+ for i, (score, age) in enumerate (arr):
74
89
for j in range (i):
75
- if nums[i][1 ] >= nums[j][1 ]:
76
- dp[i] = max (dp[i], dp[j] + nums[i][1 ])
77
- return max (dp)
90
+ if age >= arr[j][1 ]:
91
+ f[i] = max (f[i], f[j])
92
+ f[i] += score
93
+ return max (f)
94
+ ```
95
+
96
+ ``` python
97
+ class BinaryIndexedTree :
98
+ def __init__ (self , n ):
99
+ self .n = n
100
+ self .c = [0 ] * (n + 1 )
101
+
102
+ def update (self , x , val ):
103
+ while x <= self .n:
104
+ self .c[x] = max (self .c[x], val)
105
+ x += x & - x
106
+
107
+ def query (self , x ):
108
+ s = 0
109
+ while x:
110
+ s = max (s, self .c[x])
111
+ x -= x & - x
112
+ return s
113
+
114
+
115
+ class Solution :
116
+ def bestTeamScore (self , scores : List[int ], ages : List[int ]) -> int :
117
+ m = max (ages)
118
+ tree = BinaryIndexedTree(m)
119
+ for score, age in sorted (zip (scores, ages)):
120
+ tree.update(age, score + tree.query(age))
121
+ return tree.query(m)
78
122
```
79
123
80
124
### ** Java**
@@ -85,77 +129,225 @@ class Solution:
85
129
class Solution {
86
130
public int bestTeamScore (int [] scores , int [] ages ) {
87
131
int n = ages. length;
88
- int [][] nums = new int [n][2 ];
132
+ int [][] arr = new int [n][2 ];
89
133
for (int i = 0 ; i < n; ++ i) {
90
- nums [i] = new int [] {ages [i], scores [i]};
134
+ arr [i] = new int [] {scores [i], ages [i]};
91
135
}
92
- Arrays . sort(nums , (a, b) - > { return a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]; } );
93
- int [] dp = new int [n];
136
+ Arrays . sort(arr , (a, b) - > a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]);
137
+ int [] f = new int [n];
94
138
int ans = 0 ;
95
139
for (int i = 0 ; i < n; ++ i) {
96
- dp[i] = nums[i][1 ];
97
140
for (int j = 0 ; j < i; ++ j) {
98
- if (nums [i][1 ] >= nums [j][1 ]) {
99
- dp [i] = Math . max(dp [i], dp[j] + nums[i][ 1 ]);
141
+ if (arr [i][1 ] >= arr [j][1 ]) {
142
+ f [i] = Math . max(f [i], f[j ]);
100
143
}
101
144
}
102
- ans = Math . max(ans, dp[i]);
145
+ f[i] += arr[i][0 ];
146
+ ans = Math . max(ans, f[i]);
103
147
}
104
148
return ans;
105
149
}
106
150
}
107
151
```
108
152
153
+ ``` java
154
+ class BinaryIndexedTree {
155
+ private int n;
156
+ private int [] c;
157
+
158
+ public BinaryIndexedTree (int n ) {
159
+ this . n = n;
160
+ c = new int [n + 1 ];
161
+ }
162
+
163
+ public void update (int x , int val ) {
164
+ while (x <= n) {
165
+ c[x] = Math . max(c[x], val);
166
+ x += x & - x;
167
+ }
168
+ }
169
+
170
+ public int query (int x ) {
171
+ int s = 0 ;
172
+ while (x > 0 ) {
173
+ s = Math . max(s, c[x]);
174
+ x -= x & - x;
175
+ }
176
+ return s;
177
+ }
178
+ }
179
+
180
+
181
+ class Solution {
182
+ public int bestTeamScore (int [] scores , int [] ages ) {
183
+ int n = ages. length;
184
+ int [][] arr = new int [n][2 ];
185
+ for (int i = 0 ; i < n; ++ i) {
186
+ arr[i] = new int [] {scores[i], ages[i]};
187
+ }
188
+ Arrays . sort(arr, (a, b) - > a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]);
189
+ int m = 0 ;
190
+ for (int age : ages) {
191
+ m = Math . max(m, age);
192
+ }
193
+ BinaryIndexedTree tree = new BinaryIndexedTree (m);
194
+ for (int [] x : arr) {
195
+ tree. update(x[1 ], x[0 ] + tree. query(x[1 ]));
196
+ }
197
+ return tree. query(m);
198
+ }
199
+ }
200
+ ```
201
+
109
202
### ** C++**
110
203
111
204
``` cpp
112
205
class Solution {
113
206
public:
114
207
int bestTeamScore(vector<int >& scores, vector<int >& ages) {
115
208
int n = ages.size();
116
- vector<vector<int >> nums(n);
117
- for (int i = 0; i < n; ++i) nums[ i] = {ages[ i] , scores[ i] };
118
- sort(nums.begin(), nums.end());
119
- vector<int > dp(n);
209
+ vector<pair<int, int>> arr(n);
210
+ for (int i = 0; i < n; ++i) {
211
+ arr[ i] = {scores[ i] , ages[ i] };
212
+ }
213
+ sort(arr.begin(), arr.end());
214
+ vector<int > f(n);
120
215
for (int i = 0; i < n; ++i) {
121
- dp[ i] = nums[ i] [ 1 ] ;
122
216
for (int j = 0; j < i; ++j) {
123
- if (nums[ i] [ 1 ] >= nums[ j] [ 1 ] )
124
- dp[ i] = max(dp[ i] , dp[ j] + nums[ i] [ 1 ] );
217
+ if (arr[ i] .second >= arr[ j] .second) {
218
+ f[ i] = max(f[ i] , f[ j] );
219
+ }
125
220
}
221
+ f[ i] += arr[ i] .first;
126
222
}
127
- return * max_element(dp.begin(), dp.end());
223
+ return * max_element(f.begin(), f.end());
224
+ }
225
+ };
226
+ ```
227
+
228
+ ```cpp
229
+ class BinaryIndexedTree {
230
+ public:
231
+ BinaryIndexedTree(int _n) : n(_n), c(_n + 1) {}
232
+
233
+ void update(int x, int val) {
234
+ while (x <= n) {
235
+ c[x] = max(c[x], val);
236
+ x += x & -x;
237
+ }
238
+ }
239
+
240
+ int query(int x) {
241
+ int s = 0;
242
+ while (x) {
243
+ s = max(s, c[x]);
244
+ x -= x & -x;
245
+ }
246
+ return s;
247
+ }
248
+
249
+ private:
250
+ int n;
251
+ vector<int> c;
252
+ };
253
+
254
+ class Solution {
255
+ public:
256
+ int bestTeamScore(vector<int>& scores, vector<int>& ages) {
257
+ int n = ages.size();
258
+ vector<pair<int, int>> arr(n);
259
+ for (int i = 0; i < n; ++i) {
260
+ arr[i] = {scores[i], ages[i]};
261
+ }
262
+ sort(arr.begin(), arr.end());
263
+ int m = *max_element(ages.begin(), ages.end());
264
+ BinaryIndexedTree tree(m);
265
+ for (auto& [score, age] : arr) {
266
+ tree.update(age, score + tree.query(age));
267
+ }
268
+ return tree.query(m);
128
269
}
129
270
};
130
271
```
131
272
132
273
### ** Go**
133
274
134
275
``` go
135
- func bestTeamScore(scores []int, ages []int) int {
276
+ func bestTeamScore (scores []int , ages []int ) ( ans int ) {
136
277
n := len (ages)
137
- nums := make([][]int, n)
138
- for i, age := range ages {
139
- nums [i] = []int{age, scores [i]}
278
+ arr := make ([][2 ]int , n)
279
+ for i := range ages {
280
+ arr [i] = [2 ]int {scores[i], ages [i]}
140
281
}
141
- sort.Slice(nums, func(i, j int) bool {
142
- if nums[i][0] != nums[j][0] {
143
- return nums[i][0] < nums[j][0]
144
- }
145
- return nums[i][1] < nums[j][1]
282
+ sort.Slice (arr, func (i, j int ) bool {
283
+ a , b := arr[i], arr[j]
284
+ return a[0 ] < b[0 ] || a[0 ] == b[0 ] && a[1 ] < b[1 ]
146
285
})
147
- dp := make([]int, n)
148
- ans := 0
149
- for i, num := range nums {
150
- dp[i] = num[1]
286
+ f := make ([]int , n)
287
+ for i := range arr {
151
288
for j := 0 ; j < i; j++ {
152
- if num[ 1] >= nums [j][1] {
153
- dp [i] = max(dp [i], dp[j]+num[1 ])
289
+ if arr[i][ 1 ] >= arr [j][1 ] {
290
+ f [i] = max (f [i], f[j ])
154
291
}
155
292
}
156
- ans = max(ans, dp[i])
293
+ f[i] += arr[i][0 ]
294
+ ans = max (ans, f[i])
295
+ }
296
+ return
297
+ }
298
+
299
+ func max (a , b int ) int {
300
+ if a > b {
301
+ return a
302
+ }
303
+ return b
304
+ }
305
+ ```
306
+
307
+ ``` go
308
+ type BinaryIndexedTree struct {
309
+ n int
310
+ c []int
311
+ }
312
+
313
+ func newBinaryIndexedTree (n int ) *BinaryIndexedTree {
314
+ c := make ([]int , n+1 )
315
+ return &BinaryIndexedTree{n, c}
316
+ }
317
+
318
+ func (this *BinaryIndexedTree ) update (x , val int ) {
319
+ for x <= this.n {
320
+ this.c [x] = max (this.c [x], val)
321
+ x += x & -x
322
+ }
323
+ }
324
+
325
+ func (this *BinaryIndexedTree ) query (x int ) int {
326
+ s := 0
327
+ for x > 0 {
328
+ s = max (s, this.c [x])
329
+ x -= x & -x
330
+ }
331
+ return s
332
+ }
333
+
334
+ func bestTeamScore (scores []int , ages []int ) int {
335
+ n := len (ages)
336
+ arr := make ([][2 ]int , n)
337
+ m := 0
338
+ for i , age := range ages {
339
+ m = max (m, age)
340
+ arr[i] = [2 ]int {scores[i], age}
341
+ }
342
+ sort.Slice (arr, func (i, j int ) bool {
343
+ a , b := arr[i], arr[j]
344
+ return a[0 ] < b[0 ] || a[0 ] == b[0 ] && a[1 ] < b[1 ]
345
+ })
346
+ tree := newBinaryIndexedTree (m)
347
+ for _ , x := range arr {
348
+ tree.update (x[1 ], x[0 ]+tree.query (x[1 ]))
157
349
}
158
- return ans
350
+ return tree. query (m)
159
351
}
160
352
161
353
func max (a , b int ) int {
@@ -175,19 +367,19 @@ func max(a, b int) int {
175
367
* @return {number}
176
368
*/
177
369
var bestTeamScore = function (scores , ages ) {
178
- const nums = ages .map ((age , i ) => [age, scores[i]]);
179
- nums .sort ((a , b ) => (a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]));
180
- const n = nums .length ;
181
- let dp = new Array (n);
370
+ const arr = ages .map ((age , i ) => [age, scores[i]]);
371
+ arr .sort ((a , b ) => (a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]));
372
+ const n = arr .length ;
373
+ const f = new Array (n). fill ( 0 );
182
374
let ans = 0 ;
183
375
for (let i = 0 ; i < n; ++ i) {
184
- dp[i] = nums[i][1 ];
185
376
for (let j = 0 ; j < i; ++ j) {
186
- if (nums [i][1 ] >= nums [j][1 ]) {
187
- dp [i] = Math .max (dp [i], dp[j] + nums[i][ 1 ]);
377
+ if (arr [i][1 ] >= arr [j][1 ]) {
378
+ f [i] = Math .max (f [i], f[j ]);
188
379
}
189
380
}
190
- ans = Math .max (ans, dp[i]);
381
+ f[i] += arr[i][1 ];
382
+ ans = Math .max (ans, f[i]);
191
383
}
192
384
return ans;
193
385
};
0 commit comments