跳转至

abc461

AtCoder Beginner Contest 461

C

问题陈述

\(N\) 颗宝石。 \(i\) /th宝石的颜色(用整数表示)是 \(C _ i\) ,它的价值是 \(V _ i\)

从这些 \(N\) 颗宝石中选择 \(K\) 颗宝石。这里,所选的宝石必须至少有 \(M\) 种不同的颜色。

求所选宝石的最大可能总值。(在给定的输入中,这样的选择总是可能的)。

官方题解

 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
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#include<utility>
using namespace std;
using ll = long long;
const ll N=1e5+5,M=2e6+5,mod=998244353,inf=1LL<<60;
const long double pi=acos(-1);
using pii = pair<int,int>; // utility 头文件
void solve(){
    int n,k,m;
    cin >> n >> k >> m;
    vector<vector<int>> t(M+1);
    while(n--){
        int c,v;
        cin >> c >> v;
        // 优先选择价值大的,选完每个颜色中价值最大的之后,选取剩余的价值最大的
        t[c].push_back(v);
    }
    vector<int> top,tail;
    for(auto & r:t){ // 直接操作原数据,避免复制
        if(r.empty()) continue;
        sort(r.rbegin(),r.rend());
        top.push_back(r[0]);
        for(int i = 1;i<r.size();i++){
            tail.push_back(r[i]);
        }
    }
    sort(top.rbegin(),top.rend());
    for(int i = m;i<top.size();i++){
        tail.push_back(top[i]);
    }
    sort(tail.rbegin(),tail.rend());
    ll sum = 0;
    for(int i = 0;i<m && i<top.size();i++){
        sum += top[i];
    }
    int need = k-m;
    for(int i = 0;i<need && i<tail.size();i++){
        sum += tail[i];
    }
    cout << sum << endl;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cout << fixed << setprecision(10);
    int T=1;
    //cin >> T;
    while(T--) solve();
    return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 官方题解代码
N, K, M = map(int, input().split())
# 读取一行输入,按照空格切割字符串,转换成整数类型
t = [[] for _ in range(N + 1)]
# 循环 N + 1 次每次都创建一个空列表
for i in range(N): # 循环 N 次读入 N 个物品
    C, V = map(int, input().split()) # 读取输入
    t[C].append(V) # 把价值 V 放进对应类别 C 的列表里


# 声明了两个空列表
top = [] # 用来存储一开始每个相同颜色物品中价值最大的
tail = [] # 存储剩余的最大的
for r in t:
    if len(r) > 0:
        r.sort(reverse=True) # 把这个类别的价值从大到小进行排序
        top.append(r[0])
        tail += r[1:] # 把除了最大的那个元素,其余的元素全部追加到 tail 列表中

top.sort(reverse=True) # 降序排序
tail += top[M:] # 
tail.sort(reverse=True) # 降序排序
print(sum(top[:M]) + sum(tail[: K - M]))

D

问题陈述

有一个 \(H \times W\) 网格,每个单元格都包含一个整数 \(0\)\(1\)
每个单元格中写入的整数信息是长度为 \(W\)\(H\) 字符串 \(S _ 1, S _ 2, \dots, S _ H\) 。如果 \(S _ i\) 的第 \(j\) 个字符是 0 ,那么 \(0\) 就会被写入网格中从上往下第 \(i\) 行、从左往上第 \(j\) 列的单元格中;如果 \(S _ i\) 的第 \(j\) 个字符是 1 ,那么 \(1\) 就会被写入该单元格中。

求写入的整数之和等于 \(K\) 的矩形区域的个数。
更具体地说,求满足以下所有条件的整数四元组 \((r _ 1, c _ 1, r _ 2, c _ 2)\) 的个数:

  • \(1 \le r _ 1 \le r _ 2 \le H\)
  • \(1 \le c _ 1 \le c _ 2 \le W\)
  • 写在从上到下第 \(i\) 行和从左到右第 \(j\) 列的单元格中的整数,在满足 \(r _ 1 \le i \le r _ 2, c _ 1 \le j \le c _ 2\) 的所有整数对 \((i, j)\) 中的总和等于 \(K\)
    1