2000(966div3)
A. Primary Task
德米特里在黑板上写下了
整数
德米特里想知道黑板上的整数哪些可能是重要整数,哪些不可能。
void solve() {
string s;cin >> s;
if (s.size() <= 2) {
cout << "NO\n";return;
}
if (s[0] == '1' && s[1] == '0') {
if (s[2] != '0') {
if (s.size() == 3 && s[2] == '1') {
cout << "NO\n";
} else {
cout << "YES\n";
}
} else {
cout << "NO\n";
}
} else {
cout << "NO\n";
}
}
B. Seating in a Bus
在伯兰,一辆公共汽车由一排
- 如果车上没有空座位,乘客可以坐在任何空座位上;
- 否则,乘客应坐在至少有一个邻座空闲的座位上。换句话说,只有当
或 中至少有一个座位有人时,乘客才能坐在索引为 ( )的座位上。
今天有
您知道数组
void solve() {
int n;cin >> n;
vector<int> a(n + 1), mp(n + 10);
for (int i = 1;i <= n;i++)cin >> a[i];
mp[a[1]] = 1;
for (int i = 2;i <= n;i++) {
if (mp[a[i] + 1] || mp[a[i] - 1]) {
mp[a[i]] = 1;
} else {
cout << "NO\n";return;
}
}
cout << "YES\n";
}
C. Numeric String Template
克里斯蒂娜有一个由
如果同时满足以下所有条件,则认为字符串
- 字符串
的长度等于数组 中的元素个数。 - 来自
的相同数字对应于来自 的相同符号。因此,如果 ,那么 为( )。 - 来自
的相同符号对应于来自 的相同数字。因此,如果是 ,那么 为( )。
换句话说,字符串中的字符与数组中的元素必须一一对应。
乍一看是
的,其实种类超过 26 种就不可能了,所以计算量是很少的
void solve() {
int n;cin >> n;
set<int>st;
map<int, vector<int>>mp;
for (int i = 1;i <= n;i++) {
int x;cin >> x, st.insert(x), mp[x].push_back(i);
}
vector<int> bt;
for (auto [x, y] : mp) {
bt.push_back(*y.begin());
}
int m;cin >> m;
while (m--) {
string s;cin >> s;
if (s.size() != n || st.size() > 26) {
cout << "NO\n";continue;
}
s = ' ' + s;
int ok = 1;
for (auto [x, y] : mp) {
set<char>ss;
for (auto z : y) {
ss.insert(s[z]);
}
if (ss.size() != 1) {
ok = 0;
}
}
set<char>ss;
for (auto t : bt) {
ss.insert(s[t]);
}
if (ss.size() != bt.size()) {
ok = 0;
}
if (ok) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
}
D. Right Left Wrong
弗拉德发现了一个由
其中所有
弗拉德邀请您尝试进行任意数量(可能为零)的运算,以获得尽可能高的分数。
在一次操作中,您可以选择两个索引
- 将
分数添加到当前分数中; - 将所有
的 替换为'.',这意味着您不能再选择这些索引。
最大得分是多少?
贪心的做,每次都尽量选最多即可。
#define int long long
void solve() {
int n;cin >> n;
vector<int> a(n + 1);
for (int i = 1;i <= n;i++)cin >> a[i];
partial_sum(a.begin() + 1, a.end(), a.begin() + 1);
string s;cin >> s;s = ' ' + s;
vector<int> l, r;
for (int i = 1;i <= n;i++) {
if (s[i] == 'L')l.push_back(i);
}
for (int i = n;i >= 1;i--) {
if (s[i] == 'R')r.push_back(i);
}
while (l.size() > r.size()) {
l.pop_back();
}
while (r.size() > l.size()) {
r.pop_back();
}
int ans = 0;
for (int i = l.size() - 1;i >= 0;i--) {
if (l[i] < r[i]) {
ans += a[r[i]] - a[l[i] - 1];
}
}
cout << ans << '\n';
}
E. Photoshoot for Gorillas
你非常喜欢大猩猩,所以决定为它们组织一次摄影活动。大猩猩生活在丛林中。丛林是由
该排列的奇观等于边长为
一个子方格的奇观等于该子方格中大猩猩的高度之和。
从所有合适的排列中,选择最大的排列。
Solution
其实就是计算每个单元格分别能够被计算几次,我这里想得太复杂了... 以后思维需要清晰一些
#include <bits/stdc++.h>
using ll = long long;
using namespace std;
#define int long long
void solve() {
int n, m, k;cin >> n >> m >> k;
int w;cin >> w;
vector<int> a(w);
for (int i = 0;i < w;i++)cin >> a[i];
vector<int> f;
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
int res = (min(i, n - k) - max(0ll, i - k + 1) + 1) * (min(j, m - k) - max(0ll, j - k + 1) + 1);
f.push_back(res);
}
}
sort(a.rbegin(), a.rend());
sort(f.rbegin(), f.rend());
int ans = 0;
for (int i = 0;i < w;i++) {
ans += a[i] * f[i];
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_--)
solve();
}
F. Color Rows and Columns
你们有
您可以无限次地执行以下操作:选择一个矩形和其中的一个单元格,然后为其着色。
每次为任意一行或任意一列完全着色,你都可以获得
Solution
DP
对于一个矩形的操作方式是:看行和列,先得到行列小的那个分,这时相当于行/列这时减少了 1 ,再继续操作
void solve() {
int n, tar;cin >> n >> tar;
vector<vector<int>> dp(n + 1, vector<int>(tar + 1, 1e9));
dp[0][0] = 0;
for (int i = 1;i <= n;i++) {
int x, y;cin >> x >> y;int xy = x + y;
int cost = 0;
for (int j = 0;j <= xy;j++) {
for (int k = 0;k + j <= tar;k++) {
dp[i][j + k] = min(dp[i][j + k], dp[i - 1][k] + cost);
}
if (j < xy) {
if (x >= y) {
x--;cost += y;
} else {
y--;cost += x;
}
}
}
}
if (dp[n][tar] == 1e9)dp[n][tar] = -1;
cout << dp[n][tar] << '\n';
}