A. Catch the Coin
题目大意
给定一个无限大的网格,网格内分布着一些硬币。硬币会在每次行动之后往下掉落一格。
初始位置在(0,0),可以向周围八个方向上移动。
问对于每个硬币来说,是否可以被接到。
思路
只需要考虑在-1上方的即可,对于这些通过移动必然可以取到。
因为是先移动,再硬币掉落,所以考虑-1位置也满足。
横向距离没有意义,可以斜着走。
代码实现
void solve() {
ll n; cin >> n;
vector<pair<ll, ll>>o(n);
for (int i = 0; i < n; i++) {
cin >> o[i].first >> o[i].second;
if (-1 <= o[i].second) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
}
B. Substring and Subsequence
题目大意
给定两个串,要求求出一个最短串,其中包含子串a和子序列b。
思路
A作为子串,字符的相对位置不能变,所以我们可以根据A串做匹配。
看B串中最多多少个连续的字符可以与A串对应。
代码实现
void solve() {
string a, b; cin >> a >> b;
ll ans = LLONG_MAX;
for (int l = 0; l < b.size(); l++) {
ll cnt = 0;
ll lll = l;
for (int i = 0; i < a.size(); i++) {
if (b[lll] == a[i]) {
lll++;
cnt++;
}
if (lll == b.size())break;
}
ans = min(ans, (ll)b.size() - cnt + (ll)a.size());
}
cout << ans << "\n";
}
C. Two Movies
题目大意
有两部电影,n个人每个人分别对这两部电影进行评价,每个人的评价只取其中一个,要求两部电影中获得最小值的最高分。
思路
考虑贪心。
对于评价 1 -1 、-1 1 ,0 1,1 0,这些情况,我们只需要取1加上即可,对答案做正贡献。
对于1 1,我们考虑哪个少就给哪个加。
对于-1 -1,我们考虑哪个多就给哪个减。
代码实现
void solve() {
ll n; cin >> n;
vector<pair<ll, ll>>o(n);
for (int i = 0; i < n; i++) {
cin >> o[i].first;
}
for (int i = 0; i < n; i++) {
cin >> o[i].second;
}
ll yy = 0, nn = 0;
ll ans1 = 0;
ll ans2 = 0;
for (int i = 0; i < n; i++) {
if (o[i].first == o[i].second && o[i].first == 1)yy++;
else if (o[i].first == o[i].second && o[i].first == -1)nn++;
else {
if (o[i].first > o[i].second)ans1 += o[i].first;
else ans2 += o[i].second;
}
}
while (yy || nn) {
if (yy) {
yy--;
if (ans1 < ans2) {
ans1 += 1;
}
else {
ans2 += 1;
}
}
else {
nn--;
if (ans1 > ans2) {
ans1 -= 1;
}
else {
ans2 -= 1;
}
}
}
cout << min(ans1, ans2) << "\n";
}
D. Smithing Skill
题目大意
给定n种武器,每个武器被铸造和融化均会提供一点经验值。
对于每个武器,铸造需要消耗x个同种材料,融化得到y个同种材料。
给定m种材料,要求求出最大经验值。
思路
正解应该为DP,本文介绍另种非正解做法,可以卡过去。
对于武器,我们优先去做x-y更小的。
然后循环每个武器,我们可以按照材料的多少从大到小进行判断,该个武器可以做多少个。
大致思路定下来,开始优化部分逻辑。
对于同一数量的材料,我们可以一起进行处理,类似去做离散化。
(下面代码来自队友,自己写的空间没卡过去,感觉比较神奇)
代码实现
struct node {
ll a, b;
};
node arr[2000002];
bool cmp3(node x, node y) {
return (x.a - x.b) < (y.a - y.b);
}
void solve() {
ll n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> arr[i].a;
}
for (int i = 1; i <= n; i++) {
cin >> arr[i].b;
}
map<ll, ll>crr;
priority_queue<ll>brr;
map<ll, ll>mark;
for (int i = 1; i <= m; i++) {
ll f;
cin >> f;
if (mark[f]) {
mark[f]++;
continue;
}
brr.push(f);
mark[f]++;
}
ll ans = 0;
sort(arr + 1, arr + 1 + n, cmp3);
for (int i = 1; i <= n; i++) {
while (brr.top() >= arr[i].a) {
ll x = brr.top();
brr.pop();
ll k = mark[x];
mark[x] = 0;
ll g = arr[i].a - arr[i].b;
ll s = x - arr[i].a;
ll sum = s / g + 1;
x = x - sum *g;
ans = ans + sum * k;
if (mark[x]) {
mark[x] += k;
continue;
}
else {
brr.push(x);
mark[x] = k;
}
}
}
cout << ans * 2;
}