Codeforces Round #623 (Div. 2, based on VK Cup 2019-2020 - Elimination Round, Engine)
【A.Dead Pixel】
【题目大意】
有一个a * b大小的框,让你画一个最大的不包含点(x, y)的子框,输出其大小
【解题思路】
很容易想到将其分为4个区域取最大值
【AC代码】
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int a, b, x, y;
cin >> a >> b >> x >> y;
++x, ++y;
cout << max(max((x - 1) * b, (a - x) * b), max(a * (y - 1), a * (b - y))) << '\n';
}
return 0;
}
【B.Homecoming】
【题目大意】
给你一个由A和B组成的字符串,A代表电车轨道,B代表巴士轨道,连续的A会花费a元钱,连续的B会花费b元钱,你现在有p元钱,你现在从0开始向前走,由于钱可能不够,于是你决定步行至某一站然后再坐车到n,问你步行的最短长度是多少
【解题思路】
这题题目太长了,读错了好几次
有几个坑点,首先你是从第0站出发,也就是说至少要步行1站,第二就是你只用到达第n站,至于第n站是什么可以不用管
那么可以将字符串压缩一下,直接从n - 1站出发,直到把钱用完
【AC代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int a[2], p;
string s;
int len = 0;
struct Node {
char c;
int num;
}c[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> a[0] >> a[1] >> p >> s;
int l = s.length() - 1; //最后一站不用管
len = 0;
int i = 0;
while(true) {
int index = 0;
if (s[i] == 'A') {
while (i < l && s[i] == 'A') ++i, ++index;
c[++len].c = 'A';
c[len].num = index;
}
else if (s[i] == 'B') {
while (i < l && s[i] == 'B') ++i, ++index;
c[++len].c = 'B';
c[len].num = index;
}
if (i >= l) break;
}
int tag = -1;
for (int i = len; i >= 1; --i) {
p -= a[c[i].c - 'A'];
if (p < 0) {
tag = i;
break;
}
}
if (tag == -1) cout << "1\n";
else {
int ans = 0;
for (int i = 1; i <= tag; ++i) ans += c[i].num;
cout << ans + 1 << '\n'; //最后要加上0到1的1
}
}
return 0;
}
【C.Restoring Permutation】
【题目大意】
给你一个长度为n的序列b,让你构造一个序列a使得a为1 - 2n的一个排列,且满足b[i] = min(a[2i - 1], a[2i]),输出字典序最小的a数组,若不存在则输出-1
【解题思路】
假设存在
首先要求字典序最小,那么显然我们要使a[2i - 1] = b[i]
然后考虑a[2i],如果b[i] + 1没有出现在b[1 ~ n]和a[1 ~ 2i - 1]中,那么显然a[2i] = b[i] + 1,否则考虑b[i] + 2,b[i] + 3,b[i] + 4 …… 直到满足条件
然后判断a数组是否为1 - 2n的一个排列即可
【AC代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int a[210], b[110], c[210];
bool d[110];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
memset(d, 0, sizeof(d));
for (int i = 1; i <= n; ++i) {
cin >> b[i];
d[b[i]] = true;
}
int cnt = 0;
for (int i = 1; i <= n; ++i) {
a[++cnt] = b[i];
int tmp = b[i];
while (d[tmp]) ++tmp;
d[tmp] = true;
a[++cnt] = tmp;
}
for (int i = 1; i <= cnt; ++i) {
c[i] = a[i];
}
c[0] = 0;
sort(c + 1, c + cnt + 1);
bool flag = false;
for (int i = 1; i <= cnt; ++i) {
if (c[i] == c[i - 1] + 1) continue;
flag = true;
break;
}
if(flag) cout << "-1\n";
else {
for (int i = 1; i <= cnt; ++i) cout << a[i] << " ";
cout << '\n';
}
}
return 0;
}
【D.Recommendations】
【题目大意】
有n种杂志,第i本杂志的发行量为ai,将其发行量加一所花费的时间为ti,现在想要所有杂志的发行量都不一样,问你花费的最少时间是多少
【解题思路】
先举个栗子
假设发行量为7 7 8 8 8 9 9
那么我们最后的发行量一定为7 8 9 10 11 12 13
一步一步来
先将两个7中的一个变成8
7 8 8 8 8 9 9
然后留下一个8其余变成9
7 8 9 9 9 9 9
……
直到变成7 8 9 10 11 12 13
很容易想到我们每次留下的那个一定是发行量与其相同中时间最大的那个
那么我们的程序就是要去模拟这个过程
首先建立结构体然后按照首先发行量小优先其次时间大优先排序,遍历一遍,利用优先队列存储相同发行量的时间
【AC代码】
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
struct Node {
int a, t;
inline Node() { a = t = 0; }
inline Node(register int m_a, register int m_t) {
a = m_a, t = m_t;
}
inline bool operator < (const register Node& b)const {
if (a == b.a) return t > b.t;
return a < b.a;
}
}a[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
register int n;
cin >> n;
for (register int i = 1; i <= n; ++i) cin >> a[i].a;
for (register int i = 1; i <= n; ++i) cin >> a[i].t;
sort(a + 1, a + n + 1);
register ll ans = 0;
register priority_queue<int> que;
register int i = 1;
register int cur = a[1].a; //记录当前队列中的发行量
register ll sum = 0; //保存每一次的时间累加量
while (true) {
if (que.empty() && i > n) break;
while (i <= n && a[i].a == cur) { //将与其相同的丢入队列
que.push(a[i].t);
sum += a[i].t;
++i;
}
if (!que.empty()) { //保留时间最大的那个
sum -= que.top();
que.pop();
}
if (!que.empty()) { //如果队列不为空,说明队列里的所有发行量都要加1
++cur;
}
else cur = a[i].a; //如果队列为空,那么进行下一轮的对比
ans += sum;
}
cout << ans << '\n';
return 0;
}