Educational Codeforces Round 119 (Rated for Div. 2)
A - Equal or Not Equal
题目大意
E
表示和下一个数值相等, N
表示不相等
问 这个字符串所表达的数组是否合法
思路
有一些并查集的意思
但是有一些特殊的地方,
- 如果全部都是
E
那自然不用说 - 如果想把字符串拆成两个或以上的数组, 那么两个数组首位相连时必然会产生
两个N
, 而只有一个N
的就说明不合法
所以
只要有两个以上的N
, 那么这个字符串就必然合法, 相对的, 只有一个的时候就不合法
代码
#include <iostream>
using namespace std;
const int N = 50 + 10;
int n;
string str;
int main() {
int T;
cin >> T;
while (T --) {
cin >> str;
int cnt = 0;
for (auto i : str) if (i == 'N') cnt ++;
if (cnt == 1) puts("NO");
else puts("YES");
}
return 0;
}
B - Triangles on a Rectangle
题目大意
给你一个宽为W
, 高为H
的矩形, 还有四条边上的点, 问可以构成两个点在同一条边的最大的三角形的面积是多少
题目要的是面积的二倍
思路
三角形的面积 = 底 * 高 * 2
- 高的话, 我们可以直接选择对面那条边上的点, 这样点可以随便选, 而高一定为矩形的宽或者高
- 底的话, 一定是选一条边上相距最远的点
代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
LL w, h;
LL a[4][N];
int main() {
int T;
cin >> T;
while (T --) {
cin >> w >> h;
for (int i = 0; i < 4; i ++) {
cin >> a[i][0];
for (int j = 1; j <= a[i][0]; j ++) cin >> a[i][j];
sort(a[i] + 1, a[i] + a[i][0] + 1);
}
cout << max(
h * max(a[0][a[0][0]] - a[0][1], a[1][a[1][0]] - a[1][1]),
w * max(a[2][a[2][0]] - a[2][1], a[3][a[3][0]] - a[3][1])
) << endl;
}
return 0;
}
C - BA-String
题目大意
给你一个字符串, 可以在*
的位置填写不超过k
个的b
字符, 问第x
小的字符串是什么
思路
被a
分割开许多的*
串, 在简化之后, 我们发现可以在a
的左右填写不超过*
串长度的b
字符
而第x
小, 必然是先在最后一个*
串位置填写b
, 而当*
串达到最大时, 会在前一个*
串填写一个, 并在这里重新填写
于是发现, 类似与一个每一位进制都不相同的加法, 而我们寻找的正是以他为进制的第x - 1
个
代码
(写的并不是很好, 如果有更好的可以分享给我)
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10;
LL n, k, x;
string str;
LL a[N], b[N];
int idx, idx2;
void calc(LL n, LL k) {
for (int i = n; i >= 0; i --) {
b[i] = k % (a[i] + 1);
k /= (a[i] + 1);
}
}
int main() {
int T;
cin >> T;
while (T --) {
cin >> n >> k >> x;
cin >> str;
idx = idx2 = 0;
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
for (int i = 0; i < n; i ++) {
if (str[i] == 'a') {
if (a[idx]) idx ++;
}
else a[idx] += k;
}
//for (int i = 0; i <= idx; i++) cout << a[i] << ' ';
calc(idx, x - 1);
//for (int i = 0; i <= idx; i ++) cout << b[i] << ' ';
for (int i = 0; i < n; i ++) {
if (str[i] == 'a') {
if (i != 0 && str[i - 1] == '*') {
for (int i = 0; i < b[idx2]; i ++) cout << 'b';
idx2 ++;
}
cout << 'a';
}
}
if (idx2 <= idx)
while (idx2 <= idx) {
for (int i = 0; i < b[idx2]; i ++) cout << 'b';
idx2 ++;
}
cout << endl;
}
return 0;
}
D - Exact Change
题目大意
你有面值为1
, 2
, 3
的钱币, 而商店有许多不同价格的商品, 问每次出门需要带的最少的钱币数量, 以满足不同的商品价格
思路
首先贪心, 一定是取最多数量的3
钱币
然后就要细细讨论了
可以对着其进行参考, 写错地方还请指正
代码
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int T;
cin >> T;
while (T --) {
int n;
cin >> n;
int a[n];
int t1 = 0, t2 = 0, t3 = 0;
for (int i = 0; i < n; i ++) {
cin >> a[i];
if (a[i] % 3 == 0) t3 = max(t3, a[i]);
if (a[i] % 3 == 1) t1 = 1;
if (a[i] % 3 == 2) t2 = 1;
}
sort(a, a + n);
int ans;
if (a[n - 1] % 3 == 0) {
ans = a[n - 1] / 3 + (t1 || t2);
}
else if (a[n - 1] % 3 == 2) {
ans = a[n - 1] / 3 + 1 + t1;
}
else {
ans = a[n - 1] / 3 + 1 + (t2 && (a[0] == 1 || t3 + 1 == a[n - 1]));
}
cout << ans << endl;
}
return 0;
}
E - Replace the Numbers
题目大意
在很多操作过后, 求数组最后的值为多少
1 x
, 表示插入x2 x y
表示将之前所有的x变为y
思路
听说有维护数值关系, 和维护位置关系, 这里使用的是维护位置关系
维护数据用不了传统的并查集?
在map<int, list>中存下当值为int时, 所有的位置list
list可以很方便的进行转移
代码
#include <iostream>
#include <algorithm>
#include <map>
#include <list>
#include <cstdio>
#include <unordered_map>
using namespace std;
const int N = 5e5 + 10;
int n, idx;
int a[N];
unordered_map<int, list<int> > q;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
int op;
scanf("%d", &op);
if (op == 1) {
int x;
scanf("%d", &x);
q[x].push_back(idx ++);
}
else {
int x, y;
scanf("%d%d", &x, &y);
if (x == y) continue;
auto it = q.find(x);
if (it != q.end()) {
q[y].splice(q[y].begin(), q[x]);
q.erase(it);
}
}
}
for (auto &i : q) {
for (auto &j : i.second)
a[j] = i.first;
}
for (int i = 0; i < idx; i ++) printf("%d ", a[i]);
return 0;
}