2020牛客暑期多校训练营(第三场)

A-Clam and Fish

https://ac.nowcoder.com/acm/contest/5668/A

题意

给出一个字符串,每一位代表一个状态,0代表没有鱼也没有无法获得鱼饵,1代表没有鱼但可以获得鱼饵,2代表有鱼无法获得鱼饵,3代表既有鱼又可以获得鱼饵,如果有鱼可以直接钓鱼,有鱼饵可以获得一个鱼饵,可以消耗一个鱼饵钓鱼,每个状态只可以进行一次操作,问最多能钓上多少鱼

题解

能直接钓鱼就直接钓鱼,对于鱼饵,先在那些无法获得鱼饵的池子消耗鱼饵钓鱼,再加上剩下的鱼饵除以2向下取整即为答案

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 2e6 + 50;
char s[N];
int main() {
    int t; scanf("%d", &t);
    while (t--) {
        int n; scanf("%d", &n);
        scanf("%s", s + 1);
        int now = 0, ans = 0;
        for (int i = 1; i <= n; i++) {
            if (s[i] == '0') if (now > 0) now--, ans++;
            if (s[i] == '1') now++;
            if (s[i] == '2') ans++;
            if (s[i] == '3') ans++;
        }
        ans += now / 2;
        printf("%d
", ans);
    }
    return 0;
}

B-Classical String

https://ac.nowcoder.com/acm/contest/5668/B

题意

给出一个字符串,2种操作

M x,如果x大于0,把前缀长度为x的字符串移到最后,否则把前缀长度为(|x|)的后缀移到最前面

A x,询问x位置的字符是什么

题解

维护修改操作的前缀和,可以发现前缀和的值等价于修改的总和,从当前前缀和的位置向后找即可,直接取模

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
struct READ {
    inline char read() {
    #ifdef Artoriax
        return getchar();
    #endif
        const int LEN = 1 << 18 | 1;
        static char buf[LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
    }
    inline READ & operator >> (char *s) {
        char ch;
        while (isspace(ch = read()) && ~ch);
        while (!isspace(ch) && ~ch) *s++ = ch, ch = read(); *s = '';
        return *this;
    }
    inline READ & operator >> (string &s) {
        s = ""; char ch;
        while (isspace(ch = read()) && ~ch);
        while (!isspace(ch) && ~ch) s += ch, ch = read();
        return *this;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        char ch, flag;
        for(ch = read(),flag = 0; !isdigit(ch) && ~ch; ch = read()) flag |= ch == '-';
        for(x = 0; isdigit(ch); ch = read()) x = x * 10 + (ch ^ '0');
        flag && (x = -x);
        return *this;
    }
} in;

const int N = 2e6 + 50;
char s[N];
int main() {
    in >> s;
    int len = strlen(s);
    int m; in >> m;
    int now = 0;
    while (m--) {
        char ch[2]; in >> ch;
        int x; in >> x;
        if (ch[0] == 'M') now = (now + x) % len;
        else {
            int pos = (now + x - 1 + len) % len;
            printf("%c
", s[pos]);
        }
    }
    return 0;
}

C-Operation Love

https://ac.nowcoder.com/acm/contest/5668/C

题意

给出一个手的多边形的20个点,判断这个多边形是左手还是右手,可能有旋转和平移

题解

发现长度为9和8的线段是唯一的,把点改为逆时针顺序,直接判断是否有连续的9和8即可

判断给出的多边形是顺时针还是逆时针:

直接计算多边形面积,如果值为负,则为顺时针,否则为逆时针

计算多边形面积,按给出的点的顺序做叉积相加除以2,即为多边形面积。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 2e5 + 50;
const db eps = 1e-5;
int sgn(db x) {
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    else return 1;
}
struct point {
    db x, y;
    void read() { scanf("%lf%lf", &x, &y); }
    db operator ^ (const point &b) const {
        return x * b.y - y * b.x;
    }
    db dis(point b) {
        return hypot(x - b.x, y - b.y);
    }
} p[25];
int main() {
    int t; scanf("%d", &t);
    while (t--) {
        for (int i = 0; i < 20; i++) p[i].read();
        p[20] = p[0];
        db s = 0;
        for (int i = 0; i < 20; i++) s += p[i] ^ p[i + 1];
        if (s < 0) reverse(p, p + 20);
        p[20] = p[0], p[21] = p[1];
        for (int i = 0; i < 20; i++) {
            if (sgn(p[i].dis(p[i+1]) - 9) == 0) {
                if (sgn(p[i+1].dis(p[i+2]) - 8) == 0) puts("right");
                else puts("left");
            } 
        }
    }
    return 0;
}

D-Point Construction Problem

https://www.cnblogs.com/artoriax/p/13589527.html

E-Two Matchings

https://www.cnblogs.com/artoriax/p/13589731.html

F-Fraction Construction-Problem

https://www.cnblogs.com/artoriax/p/13589878.html

G-Operating on a Graph

题意

题解

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 8e5 + 50;
vector<int> G[N];
int f[N];
int find(int x) {
    return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(vector<int> &x, vector<int> &y) {
    if (x.size() < y.size()) swap(x, y);
    for (auto e : y) x.push_back(e);
    y.clear();
}
int main() {
    int t; in >> t;
    while (t--) {
        int n, m; in >> n >> m;
        for (int i = 1; i <= n; i++) G[i].clear(), f[i] = i;
        for (int i = 1; i <= m; i++) {
            int x, y; in >> x >> y; x++; y++;
            G[x].push_back(y);
            G[y].push_back(x);
        }
        int q; in >> q;
        while (q--) {
            int o; in >> o; o++;
            if (find(o) != o) continue;
            vector<int> tmp = G[o];
            G[o].clear();
            for (auto nx : tmp) {
                int y = find(nx);
                if (y == o) continue;
                f[y] = o;
                merge(G[o], G[y]);
            }
        }
        for (int i = 1; i <= n; i++) {
            printf("%d ", find(i) - 1);
        }
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/artoriax/p/13589931.html