AtCoder Beginner Contest 218(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 218(补题)相关的知识,希望对你有一定的参考价值。

C - Shapes



题意:

给定两个图, S S S T T T,’#'代表图案, ‘ . ’ ‘.’ .代表空,整幅图是 N ✖ N N✖N NN的大小,现在问你,能否旋转90°和平移的操作(操作数不限),来把S图中的图案,变成T中的图案

思路:

找到S图和T图中,图案的最左端、右端、上端、下端的坐标,上下左右坐标之外的地方说明都是空地,不用管,此时,此时,把新图(坐标是最左端右端上端下端之中的图),通过旋转,会有4种情况,旋转0,90,180,270,把旋转出来的图,存下来,看T图中是否有上述4种情况之一的图,可以小优化一下,如果找出来的图,一个是正方形另一个不是,那就直接不行。

#include <bits/stdc++.h>
using namespace std;
const int N = 210;
#define inf 0x3f3f3f3f
char S[N][N], T[N][N];
int n;
int u, l, r, d;
int U, L, R, D;
void change() {
    map<string, int> m;
    int f1, f2, f3, f4;
    f1 = f2 = f3 = f4 = 1;
    string s;
    for (int i = u; i <= d; i++) {
        for (int j = l; j <= r; j++) {
            s.push_back(S[i][j]);
        }
    }
    m[s]++;
    s.clear();
    for (int i = l; i <= r; i++) {
        for (int j = d; j >= u; j--) {
            s.push_back(S[j][i]);
        }
    }

    m[s]++;
    s.clear();
    for (int i = r; i >= l; i--) {
        for (int j = u; j <= d; j++) {
            s.push_back(S[j][i]);
        }
    }

    m[s]++;
    s.clear();
    for (int i = d; i >= u; i--) {
        for (int j = r; j >= l; j--) {
            s.push_back(S[i][j]);
        }
    }
    m[s]++;
    s.clear();
    for (int i = U; i <= D; i++) {
        for (int j = L; j <= R; j++) {
            s.push_back(T[i][j]);
        }
    }
    if (m[s] >= 1) {
        puts("Yes");
    } else
        puts("No");
    return;
}
int main() {
    cin >> n;
    u = U = l = L = inf;
    r = d = R = D = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> S[i][j];
            if (S[i][j] == '#') {
                u = min(u, i);
                d = max(d, i);
                l = min(l, j);
                r = max(r, j);
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> T[i][j];
            if (T[i][j] == '#') {
                U = min(U, i);
                D = max(D, i);
                L = min(L, j);
                R = max(R, j);
            }
        }
    }
    //一方为正方形,另一方不是
    if (d - u == R - l && r - l != D - U && r - l == R - L && d - u != D - U) {
        puts("No");
        return 0;
    }
    change();

    return 0;
}

D - Rectangles


题意:

n n n个点的坐标,让你找四个坐标,组成一个矩形,问有多少个矩形的边与 x x x轴,或 y y y轴平行。

思路:

直接枚举矩形的右上端点( x 1 , y 1 x_1,y_1 x1,y1)和左下端点( x 2 , y 2 x_2,y_2 x2,y2),看是否右两个点的坐标( x 1 , y 2 x_1,y_2 x1,y2)( x 2 , y 1 x_2,y_1 x2,y1)来组成一个符合题意的矩形。
找( x 1 , y 2 x_1,y_2 x1,y2)( x 2 , y 1 x_2,y_1 x2,y1)这两个坐标的方法,可以用binary_search函数来二分找,也可以用桶提前把坐标存下来,来找。

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 2020;
#define x first
#define y second
int n;
int main() {
    scanf("%d", &n);
    vector<PII> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i].x >> a[i].y;
    }
    sort(a.begin(), a.end());
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (a[i].x < a[j].x && a[i].y < a[j].y) {
                if (binary_search(a.begin(), a.end(),
                                  make_pair(a[i].x, a[j].y)) &&
                    binary_search(a.begin(), a.end(),
                                  make_pair(a[j].x, a[i].y))) {
                    res++;
                }
            }
        }
    }
    printf("%d\\n", res);
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct node {
    int x, y;
} e[N];
map<int, map<int, int>> vis;
int n;
bool cmp(node a, node b) {
    if (a.x != b.x) return a.x < b.x;
    return a.y < b.y;
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> e[i].x >> e[i].y;
        vis[e[i].x][e[i].y] = 1;
    }
    sort(e + 1, e + n + 1, cmp);
    int res = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (e[i].x < e[j].x && e[i].y < e[j].y) {
                if (vis[e[i].x][e[j].y] == 1 && vis[e[j].x][e[i].y] == 1) {
                    res++;
                }
            }
        }
    }
    cout << res << endl;
}

E - Destruction


题意:

给你一张连通图, n n n个点 m m m条边,现在让你在满足图是连通的情况下,删除一些边w,如果删除的边是正的,你将会得到+w的价值,如果删除的边是负的,你将会得到-w的价值,现在让你删除一些边,并保证图是连通的,问你能得到的最大价值。

思路:

所有边的权值和 − - 最小生成树(这个不是严格的最小生成树,所有负数边全放在生成树边中)的边权和= a n s ans ans

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, M = N * 2;
#define int long long
struct node {
    int a, b;
    int w;
    bool operator<(const node &t) const { return w < t.w; }
} e[M];
int fa[N];

int n, m;
int find(int x) {
    if (x != fa[x]) fa[x] = find(fa[x]);
    return fa[x];
}

signed main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        fa[i] = i;
    }
    int sum = 0;
    for (int i = 0; i < m; i++) {
        int a, b, c;
        scanf("%lld%lld%lld", &a, &b, &c);
        e[i] = {a, b, c};
        sum += c;
    }
    sort(e, e + m);
    int res = 0;
    for (int i = 0; i < m; i++) {
        int a = e[i].a, b = e[i].b, c = e[i].w;
        a = find(a), b = find(b);
        if (a != b || (c < 0)) {
            fa[a] = b;
            res += c;
        }
    }
    cout << sum - res << endl;
}

F - Blocked Roads



题意:

给你一个 n n n个点

以上是关于AtCoder Beginner Contest 218(补题)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242