A题:The bottom of the ninth
题目大意:
两人进行共计9把比赛,现已知道打了8.5把的两人比分情况,选手A的分数大于等于B,问选手B最少要在下半场赢多少分,才能使分数高于A。
思路:
加起来减去即可,注意分数要求大于。
// Problem: A - The bottom of the ninth
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int x = 0, cnt = 9;
while (cnt -- ) {
int t; cin >> t;
x += t;
}
cnt = 8;
while (cnt -- ) {
int t; cin >> t;
x -= t;
}
cout << x + 1 << endl;
return 0;
}
B题: Spot the Difference
题目大意:
给你两个网格,其中有一个位置两个网格上的字符不同,要求你输出这个位置。
思路:
模拟即可。
// Problem: B - Spot the Difference
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
string s[n + 1];
for (int i = 1; i <= n; i ++ ) {
string t; cin >> t;
t = " " + t;
s[i] = t;
}
int x, y;
for (int i = 1; i <= n; i ++ ) {
string t; cin >> t;
t = " " + t;
for (int j = 1; j <= n; j ++ ) {
if (s[i][j] != t[j]) {
x = i, y = j;
}
}
}
cout << x << ' ' << y << endl;
return 0;
}
C题: Merge the balls
题目大意:
一开始你得到一个空序列和N个球,每次按顺序放入一个球,如果前后两个球的值相同,那么就可以合成一个值+1的球,直到序列剩一个球或者前后不等为止。
思路:
栈的模拟,如果一样那么pop()弹出,值+1。
可证时间复杂度一定是的。
// Problem: C - Merge the balls
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
stack<ll> s;
for (int i = 1; i <= n; i ++ ) {
ll x; cin >> x;
if (s.size() && s.top() == x) {
while (s.size() && s.top() == x) {
s.pop();
x += 1;
}
}
s.push(x);
}
cout << s.size() << endl;
return 0;
}
D题: Grid and Magnet
题目大意:
你可以在一个网格上移动,一开始由你自由选择起点,要求你输出你可以到达的最多格子数。但是你会被磁铁吸住(如果你的四个方向中有#),这样你就不可以移动了。
思路:
bfs进行遍历即可。
vis数组:
众所周知,vis是来避免重复遍历的,在这个题目中,只有旁边没有磁铁#的点才可以vis打true,然后丢进queue中,因为旁边有磁铁的点是无法移动的。
可能的重复遍历:
我们不将旁边有磁铁的点丢进去,那是不是我们就不用管它的vis了呢?肯定不是,如果这个点的四周有多个旁边没有磁铁的点(被丢进queue里面的),这样就会重复计算,使得答案变大。如果要避免重复,我们需要修改vis,vis也不能简单的赋成1,因为旁边有磁铁的点可能被不同的连通块遍历到,它都能给它们提供贡献。(可以试试样例)
我这里利用了一个cnt表示它在哪一个连通块中。
// Problem: D - Grid and Magnet
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
int ans = 1, cnt = 5;
int h, w;
int vis[1010][1010];
bool check(int x, int y) {
bool ok = true;
for (int i = 0; i < 4; i ++ ) {
int u = x + dx[i], v = y + dy[i];
if (vis[u][v] == 2) ok = false;
}
return ok;
}
void bfs(int x, int y) {
int res = 1;
queue<PII> q;
q.push({x, y});
vis[x][y] = 1;
while (q.size()) {
auto t = q.front(); q.pop();
int x1 = t.first, y1 = t.second;
for (int i = 0; i < 4; i ++ ) {
int x2 = x1 + dx[i], y2 = y1 + dy[i];
if (x2 < 1 || x2 > h || y2 < 1 || y2 > w) continue;
if (vis[x2][y2] == 1 || vis[x2][y2] == 2) continue;
if (!check(x2, y2)) {
if (vis[x2][y2] == cnt) continue;
vis[x2][y2] = cnt;
res += 1;
}
else {
res += 1;
vis[x2][y2] = 1;
q.push({x2, y2});
}
}
}
ans = max(ans, res);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> h >> w;
for (int i = 1; i <= h; i ++ ) {
for (int j = 1; j <= w; j ++ ) {
char c; cin >> c;
if (c == '#') {
vis[i][j] = 2;
}
}
}
for (int i = 1; i <= h; i ++ ) {
for (int j = 1; j <= w; j ++ ) {
if (vis[i][j] == 0 && check(i, j)) {
bfs(i, j);
cnt += 1;
}
}
}
cout << ans << endl;
return 0;
}
E题: Jump Distance Sum
题目大意:
见题目,挺好懂的。
思路:
斜着走不适应,所以我们给向量乘以一个矩阵使其变成横竖着走。
其中角度为45度,顺时针。
这样我们要求计算的就是曼哈顿距离。
放进去的时候用x+y和y-x来,最后ans/2,这样保证精度
计算绝对值之和的时候按考虑每个值对答案的贡献进行计算即可,这样就可以sort加前缀和计算了。
// Problem: E - Jump Distance Sum
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
ll op(vector<int> &a) {
int n = a.size();
ll res = 0, sum = 0;
sort(a.begin(), a.end());
for (int i = 0; i < n; i ++ ) {
res += (ll)i * a[i] - sum;
sum += a[i];
}
return res;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
vector<int> x[2], y[2];
for (int i = 1; i <= n; i ++ ) {
int a, b; cin >> a >> b;
int t = (a + b) % 2;
x[t].push_back(a + b);
y[t].push_back(b - a);
}
ll ans = 0;
for (int i = 0; i < 2; i ++ ) {
ans += op(x[i]), ans += op(y[i]);
}
cout << ans / 2 << endl;
return 0;
}
F题: Double Sum
题目大意:
见题目,很简明。
// Problem: F - Double Sum
// Contest: AtCoder - AtCoder Beginner Contest 351
// URL: https://atcoder.jp/contests/abc351/tasks/abc351_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 4e5 + 9;
ll tr1[N], tr2[N];
PII a[N];
int n;
int lowbit(int x) {return x & (-x);}
ll query(int u, ll tr[]) {
ll res = 0;
for (int i = u; i; i -= lowbit(i)) res += tr[i];
return res;
}
void add(int u, int v, ll tr[]) {
for (int i = u; i <= n; i += lowbit(i)) tr[i] += v;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i].first;
a[i].second = i;
}
sort(a + 1, a + 1 + n);
ll ans = 0;
for (int i = 1; i <= n; i ++ ) {
ans += query(a[i].second - 1, tr1) * a[i].first - query(a[i].second - 1, tr2);
add(a[i].second, 1, tr1), add(a[i].second, a[i].first, tr2);
}
cout << ans << endl;
return 0;
}