201903

1. 小中大

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;

int n;
int a[N];

int main() 
{
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    if (a[1] < a[n]) swap(a[1], a[n]);
    if (n & 1) printf("%d %d %d\n", a[1], a[(n+1)/2], a[n]);
    else {
        int mid = a[n/2] + a[n/2+1];
        if (mid & 1) printf("%d %.1lf %d\n", a[1], 1.0 * mid / 2, a[n]);
        else printf("%d %d %d\n", a[1], mid / 2, a[n]);
    }
    return 0;
}

2. 二十四点

  很水的中缀表达式求值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N= 20;

string str;
map<char, int> op;
int n, top, cnt, sta[N];
char st[N], suff[N];

int main() 
{
    op['x'] = op['/'] = 2;
    op['+'] = op['-'] = 1;
    scanf("%d", &n);
    while (n--) {
        cin >> str;
        int len = str.length();
        cnt = top = 0;
        for (int i = 0; i < len; ++i) {
            if (isdigit(str[i])) suff[++cnt] = str[i];
            else {
                while (op[str[i]] <= op[st[top]] && top)
                    suff[++cnt] = st[top--];
                st[++top] = str[i];
            }
        }
        while (top) suff[++cnt] = st[top--];
        for (int i = 1; i <= cnt; ++i) {
            if (isdigit(suff[i])) { sta[++top] = suff[i] - '0'; continue; }
            top--;
            if (suff[i] == '+') sta[top] = sta[top] + sta[top+1];
            else if (suff[i] == '-') sta[top] = sta[top] - sta[top+1];
            else if (suff[i] == 'x') sta[top] = sta[top] * sta[top+1];
            else if (suff[i] == '/') sta[top] = sta[top] / sta[top+1];
            else top++;
        }
        if (sta[top] == 24) puts("Yes");
        else puts("No");
    }
    return 0;
}

3. 损坏的RAID5

  题面很长,找出编号相应关系后其实很简单,数据规模大,输入用 cin 需要关同步,关同步后切记 scanfprintfputs 等不能与 cincout 混用,否则会爆 0,指定的块超出阵列总长度用 try catch 处理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e3 + 5;

int n, s, l, m;
string disk[N];
map<int, int> vis;

int xtoi(char c) {
    if (isdigit(c)) return c - '0';
    return c - 'A' + 10;
}

char itox(int x) {
    if (x < 10) return x + '0';
    return x - 10 + 'A';
}

void string_xor(string &a, const string &b) {
    for (int i = 0; i < (int)a.size(); ++i)
        a[i] = itox(xtoi(a[i]) ^ xtoi(b[i]));
}

int main() 
{
    ios::sync_with_stdio(false);
    cin >> n >> s >> l;
    int x, bad = n - l;
    for (int i = 1; i <= l; ++i) {
        cin >> x;
        cin >> disk[x]; // 不能写成一行
        vis[x] = 1;
    }
    cin >> m;
    while (m--) {
        cin >> x;
        int stripe = x / s; // 条带
        int id = stripe % n; // 磁盘编号
        int k = stripe / (n - 1); // 块号
        int bik = k * s + x % s; // 真实块号
        try {
            if (vis[id]) cout << disk[id].substr(bik * 8, 8) << '\n';
            else if (bad > 1) cout << "-\n";
            else {
                string str = "00000000";
                for (int i = 0; i < n; ++i)
                    if (vis[i])
                        string_xor(str, disk[i].substr(bik * 8, 8));
                cout << str << '\n';
            }
        }
        catch (exception& e) {
            cout << "-\n";
        }
    }
    return 0;
}

/*
2 1 2
0 000102030405060710111213141516172081222324252627
1 000102030405060710111213141516172051222324252627
2
0
1
3 2 2
0 000102030405060710111213141516172081222324252627
1 A0A1A2A3A4A5A6A7B0B1B2B3B4B5B6B7C0C1C2C3C4C5C6C7
2
2
5
*/

4. 消息传递接口

  大模拟一个,存好 0 到 n - 1 号进程的命令,重复遍历,有消去继续,无消去就退出即可,这种题就是要注意下细节。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;

struct node {
    int op, pid; // op 0 接受 s 发送
};

int t, n;
int num[N], vis[N];
vector<node> p[N];

int solve() {
    memset(num, 0, sizeof(num));
    memset(vis, 0, sizeof(vis));
    int flag = 1, cnt = 0;
    while (flag) {
        flag = 0;
        for (int i = 0; i < n; ++i) {
            if (vis[i]) continue;
            if (num[i] == (int)p[i].size()) { cnt++; vis[i] = 1; continue; }
            int id = p[i][num[i]].pid;
            if (num[id] == (int)p[id].size()) return 0;
            if (!p[i][num[i]].op) {
                if (p[id][num[id]].op && p[id][num[id]].pid == i) {
                    num[i]++; num[id]++; flag = 1;
                }
                else if (!p[id][num[id]].op && p[id][num[id]].pid == i) {
                    return 0;
                }
            }
            else if (p[i][num[i]].op) {
                if (!p[id][num[id]].op && p[id][num[id]].pid == i) {
                    num[i]++; num[id]++; flag = 1;
                }
                else if (p[id][num[id]].op && p[id][num[id]].pid == i) {
                    return 0;
                }
            }
        }
        if (cnt == n) return 1;
    }
    return 0;
}

int main() 
{
    scanf("%d%d", &t, &n);
    getchar();
    while (t--) {
        char str[100];
        for (int i = 0; i < n; ++i) {
            p[i].clear();
            scanf("%[^\n]", str + 1); getchar();
            int len = strlen(str + 1);
            int op, pid = 0;
            for (int j = 1; j <= len; ++j) {
                if (str[j] == 'R') op = 0;
                else if (str[j] == 'S') op = 1;
                else if (isdigit(str[j])) pid = pid * 10 + str[j] - '0';
                else {
                    p[i].push_back({op, pid});
                    pid = 0;
                }
            }
            p[i].push_back({op, pid});
        }
        if (solve()) puts("0");
        else puts("1");
    }
    return 0;
}
/*
3 2
R1 S1
S0 R0
R1 S1
R0 S0
R1 R1 R1 R1 S1 S1 S1 S1
S0 S0 S0 S0 R0 R0 R0 R0
2 3
R1 S1
R2 S0 R0 S2
S1 R1
R1
R2 S0 R0
S1 R1
*/

5. 317号子任务

  震惊,csp 认证竟然怎么水的吗,随便写了个暴力,卡常 968ms 竟然 100pts 过了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef pair<int, int> P;
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5, M = 2e4 + 5;

int n, m, k, tot;
int ver[M], edge[M], nxt[M], head[N];
int type[N], vis[N];
int d[1005][N];
vector<int> vec;

void add(int x, int y, int z) {
    ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot;
}

void dijkstra(int st, int *dis) {
    priority_queue<P, vector<P>, greater<P> > q;
    memset(dis, 0x3f, sizeof(int) * N);
    memset(vis, 0, sizeof(vis));
    dis[st] = 0;
    q.push(P(dis[st], st));
    while (!q.empty()) {
        int x = q.top().second;
        q.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        for (int i = head[x]; i; i = nxt[i]) {
            int y = ver[i];
            if (dis[y] > dis[x] + edge[i]) {
                dis[y] = dis[x] + edge[i];
                q.push(P(dis[y], y));
            }
        }
    }
}

int main() 
{
    scanf("%d%d%d", &n, &m, &k);
    int x, y, z;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &x);
        if (x) vec.push_back(i);
    }
    while (m--) {
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z); add(y, x, z);
    }
    for (int i = 0; i < (int)vec.size(); ++i) {
        dijkstra(vec[i], d[i]);
    }
    if (k > (int)vec.size()) k = (int)vec.size();
    for (int i = 1; i <= n; ++i) {
        vector<int> dis;
        for (int x = 0; x < (int)vec.size(); ++x) {
            dis.push_back(d[x][i]);
        }
        sort(dis.begin(), dis.end());
        int ans = 0;
        for (int j = 0; j < k && dis[j] != INF; ++j) ans += dis[j];
        printf("%d\n", ans);
    }
    return 0;
}
/*
7 6 2
1 0 1 0 1 1 0
1 4 1
1 2 3
2 4 4
2 3 5
2 5 7
6 7 5
*/

201909

1. 小明种苹果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;

int n, m;

int main() 
{
    scanf("%d%d", &n, &m);
    int x, sum = 0, minn = 0, id, res;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &x); sum += x;
        res = 0;
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &x); res += x;
        }
        sum += res;
        if (res < minn) {
            id = i; minn = res;
        }
    }
    printf("%d %d %d\n", sum, id, -minn);
    return 0;
}

2. 小明种苹果(续)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1005;

int n, m;
int drop[N];

int main() 
{
    scanf("%d", &n);
    int x, sum = 0, cnt = 0, ans = 0;
    for (int i = 0; i < n; ++i) {
        scanf("%d", &m);
        int res = 0;
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &x);
            if (x > 0) {
                if (res > x) drop[i] = 1;
                res = x;
            }
            else res += x;
        }
        if (drop[i]) cnt++;
        sum += res;
    }
    for (int i = 0; i < n; ++i) {
        if (drop[i%n] && drop[(i+1)%n] && drop[(i+2)%n]) ans++;
    }
    printf("%d %d %d\n", sum, cnt, ans);
    return 0;
}
/*
5
4 10 0 9 0
4 10 -2 7 0
2 10 0
4 10 -3 5 0
4 10 -1 8 0
*/

3. 字符画

  阅读理解题(在考场上我可能直接放弃了),$m,n$ 分别表示图片的宽和高,$m\times n$ 个像素点,$p,q$ 分别表示每一块的宽和高,$p\mid m, q\mid n$。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;

struct pixel {
    int r, g, b;
    bool operator == (const pixel &rhs) const {
        return (r == rhs.r && g == rhs.g && b == rhs.b);
    }
    bool operator != (const pixel &rhs) const {
        return (r != rhs.r || g != rhs.g || b != rhs.b);
    }
};

int m, n, p, q;

void print(string &str, pixel rgb = {0, 0, 0}) {
    for (char c : str) {
        if (c == 'R' || c == 'G' || c == 'B') {
            string tmp = to_string(c == 'R' ? rgb.r : c == 'G' ? rgb.g : rgb.b);
            for (char ch : tmp) printf("\\x%02X", ch);
        }
        else printf("\\x%02X", c);
    }
}

int main() 
{
    string back = "\x1b[48;2;R;G;Bm", reset = "\x1b[0m";
    scanf("%d%d%d%d", &m, &n, &p, &q);
    vector<vector<pixel> > image(n); // 图像像素
    string str;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> str;
            if (str.size() == 2) str += string(5, str.back()); // #a
            else if (str.size() == 4) // #abc
                str = "#" + string(2, str[1]) + string(2, str[2]) + string(2, str[3]);
            image[i].push_back({stoi(str.substr(1, 2), 0, 16), stoi(str.substr(3, 2), 0, 16), stoi(str.substr(5, 2), 0, 16)});
        }
    }
    pixel lst = {0, 0, 0}, st = {0, 0, 0};
    for (int i = 0; i < n / q; ++i) {
        for (int j = 0; j < m / p; ++j) {
            pixel cur = {0, 0, 0};
            for (int r = 0; r < q; ++r) {
                for (int c = 0; c < p; ++c) {
                    cur.r += image[i*q+r][j*p+c].r;
                    cur.g += image[i*q+r][j*p+c].g;
                    cur.b += image[i*q+r][j*p+c].b;
                }
            }		
            cur.r /= p * q;
            cur.g /= p * q;
            cur.b /= p * q;
            if (cur != lst) { // 与上一块颜色不同
                if (cur == st) print(reset);
                else print(back, cur);
            }
            lst = cur;
            printf("\\x%02X", ' '); // 每块后一空格
        }
        if (lst != st) print(reset); // 每行后颜色不是默认值重置
        lst = st;
        printf("\\x%02X", '\n'); // 每行后一换行
    }
    return 0;
}

4. 推荐系统