Codeforces Round #619 (Div. 2) 简要题解

A:只要每个位置都满足a[i] = c[i]或b[i] = c[i]即可。

int main() {
    int t; scanf("%d", &t);
    while(t --) {
        char a[110], b[110], c[110];
        scanf("%s%s%s", a, b, c);
        int n = strlen(a), tag = 1;
        for(int i = 0; i < n; i ++) {
            if(a[i] == c[i] || b[i] == c[i]) {

            } else {
                tag = 0; break ;
            }
        }
        puts(tag ? "YES" : "NO");
    }
    return 0;
} 

B:写了无脑二分,实际上可以线性:k取(max - min) / 2。max和min是与-1相邻的数中最大值和最小值。

const int N = 4e5 + 10;
const int mo = 1e9 + 7;
int n, a[N], k;
bool ck(int mid) {
    ll l = 0, r = 1e9;
    for(int i = 1; i <= n; i ++) if(~ a[i]) {
        if(a[i + 1] == -1 || a[i - 1] == -1) {
            ll nl = a[i] - mid, nr = a[i] + mid;
            l = max(l, nl); r = min(r, nr);
        }
    }
    if(l <= r) k = l;
    return l <= r;
}
int main() {
    int t; scanf("%d", &t);
    while(t --) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d", a + i);
        a[0] = a[n + 1] = 0;
        int l = 0, r = 1e9, mid, ans;
        for(int i = 1; i < n; i ++) if(~ a[i] && ~ a[i + 1])
            l = max(l, a[i] > a[i + 1] ? a[i] - a[i + 1] : a[i + 1] - a[i]);
        while(l <= r) {
            mid = (l + r) >> 1;
            if(ck(mid)) r = (ans = mid) - 1;
            else l = mid + 1;
        }
        ck(ans);
        printf("%d %d\n", ans, k);
    }
    return 0;
} 

C:利用容斥思想化简式子,最后发现问题转换为:

给定\(x\)和\(k\),你需要安排\(x_i\)使得\(\sum_{i = 1}^k x_i = x\),最小化\(\sum_{i = 1}^k x_i^2\)

结论是尽可能平均分。即令\(y = \lfloor \frac{x}{k} \rfloor\),\(x \bmod k\)个元素为\(y + 1\),剩下为\(y\)

简单的证明:假设最优方案中存在\(x_i > x_j, x_i - x_j > 1\),此时\((x_i - 1)^2 + (x_j + 1)^2 = x_i^2 + x_j^2 + 2 (x_j - x_i + 1) < x_i^2 + x_j^2\),说明有更优方案。

int n, m;
ll calc(ll n) {
    return n * (n + 1) / 2;
}
ll __div(ll z, ll d) {
    ll c = z / d, r = z % d;
    return (c + 1) * (c + 1) * r + c * c * (d - r);
}
int main() {
    int t; scanf("%d", &t);
    while(t --) {
        scanf("%d%d", &n, &m);
        ll z = n - m, d = m + 1;
        printf("%lld\n", calc(n) - (z + __div(z, d)) / 2);
    }
    return 0;
} 

D:构造题,有方法把所有边都走一遍,构造方法见代码

int n, m, k;
vector< pair<string, int>  > ans;
void push(string s, int t) {
    if(t == 0) return ;
    static int x;
    int sz = (int) s.size();
    if(x + (ll) sz * t >= k) {
        int d = k - x; string tmp;
        if(d / sz > 0) ans.pb(mp(s, d / sz));
        for(int i = 0; i < d % sz; i ++) tmp.pb(s[i]);
        if(d % sz > 0) ans.pb(mp(tmp, 1));
        printf("YES\n%d\n", (int) ans.size());
        for(auto y : ans) {
            printf("%d %s\n", y.sc, y.fs.c_str());
        }
        exit(0);
    }
    ans.pb(mp(s, t)); x += sz * t;
}
int main() {
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i < n; i ++) {
        push("RDU", m - 1);
        push("L", m - 1);
        push("D", 1);
    }
    push("R", m - 1);
    push("L", m - 1);
    push("U", n - 1);
    puts("NO");
    return 0;
}

E:标算是二维ST表,实际上冷静分析可以只需二维前缀和。首先我们发现了一个简单的结论,以某个点为左上角,最多有一个满足条件的正方形。

那就直接f[len][i][j]表示(i, j)这个前缀矩形里有多少个点,以该点为左上角边长为len的正方形是合法的,询问就枚举长度用前缀和判断。

复杂度\(O(n^3 + qn)\).

const int N = 500 + 10;

int n, m, q, sum[4][N][N], Map[N], f[N][N][N];
char s[N][N];
int query(int a[N][N], int x1, int y1, int x2, int y2) {
    return a[x2][y2] - a[x1 - 1][y2] - a[x2][y1 - 1] + a[x1 - 1][y1 - 1];
}
bool judge(int x, int y, int l) {
    int mx = x + (l / 2), my = y + (l / 2);
    int sz = l * l / 4, ex = x + l - 1, ey = y + l - 1;
    if(query(sum[0], x, y, mx - 1, my - 1) != sz) return 0;
    if(query(sum[2], mx, y, ex, my - 1) != sz) return 0;
    if(query(sum[1], x, my, mx - 1, ey) != sz) return 0;
    if(query(sum[3], mx, my, ex, ey) != sz) return 0;
    return 1;
}
int main() {
    Map['R'] = 0; Map['G'] = 1; Map['Y'] = 2; Map['B'] = 3;
    scanf("%d%d%d", &n, &m, &q);
    for(int i = 1; i <= n; i ++) {
        scanf("%s", s[i] + 1);
        for(int j = 1; j <= m; j ++) {
            sum[Map[s[i][j]]][i][j] = 1;
        }
    }
    for(int k = 0; k < 4; k ++) {
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m; j ++) {
                sum[k][i][j] += sum[k][i - 1][j] + sum[k][i][j - 1] - sum[k][i - 1][j - 1];
            }
        }
    }
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) if(s[i][j] == 'R') {
            int lim = min(n - i + 1, m - j + 1);
            for(int k = 2; k <= lim; k += 2) {
                if(judge(i, j, k)) {
                    f[k][i][j] = 1; break ;
                }
            }
        }
    }
    for(int k = 2; k <= max(n, m); k += 2) {
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m; j ++) {
                f[k][i][j] += f[k][i - 1][j] + f[k][i][j - 1] - f[k][i - 1][j - 1];
            }
        }
    }
    for(int i = 0; i < q; i ++) {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        int ans = 0, lim = min(x2 - x1 + 1, y2 - y1 + 1);
        for(int k = 2; k <= lim; k += 2) {
            int ex = x2 - k + 1, ey = y2 - k + 1;
            if(query(f[k], x1, y1, ex, ey)) {
                ans = k * k;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
} 

F:做法又不同于标算,但其实大同小异。


const int N = 40 + 4;
const int M = 1004;
const int INF = 1e8 + 10;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
int n, m, k, q, a[M][M], G[N][N], d[M][M][N];
vector<pii> vec[N];
void bfs(int col) {
    queue<pii> q;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            d[i][j][col] = -1;
    for(pii u : vec[col]) {
        q.push(u); d[u.fs][u.sc][col] = 0;
    }
    while(q.size()) {
        pii u = q.front(); q.pop();
        int t = a[u.fs][u.sc];
        G[t][col] = G[col][t] = min(G[col][t], d[u.fs][u.sc][col]);
        for(int i = 0; i < 4; i ++) {
            pii v = mp(u.fs + dx[i], u.sc + dy[i]);
            if(v.fs < 1 || v.fs > n || v.sc < 1 || v.sc > m) continue ;
            if(-1 == d[v.fs][v.sc][col]) {
                d[v.fs][v.sc][col] = d[u.fs][u.sc][col] + 1;
                q.push(v);
            }
        }
    }
}
int myabs(int x) {
    return x > 0 ? x : -x;
}
int main() {
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= k; i ++)
        fill(G[i] + 1, G[i] + k + 1, INF), G[i][i] = 0;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            scanf("%d", &a[i][j]);
            vec[a[i][j]].pb(mp(i, j));
            if(i != 1 && a[i - 1][j] != a[i][j]) {
                int u = a[i - 1][j], v = a[i][j];
                G[u][v] = G[v][u] = 1;
            }
            if(j != 1 && a[i][j - 1] != a[i][j]) {
                int u = a[i][j - 1], v = a[i][j];
                G[u][v] = G[v][u] = 1;
            }
        }
    }
    for(int i = 1; i <= k; i ++) bfs(i);
    for(int w = 1; w <= k; w ++)
        for(int u = 1; u <= k; u ++)
            for(int v = 1; v <= k; v ++)
                G[u][v] = min(G[u][v], G[u][w] + G[w][v] + 1);
    scanf("%d", &q);
    for(int i = 1; i <= q; i ++) {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        int ans = myabs(x1 - x2) + myabs(y1 - y2);
        for(int x = 1; x <= k; x ++) {
            for(int y = 1; y <= k; y ++) {
                ans = min(ans, d[x1][y1][x] + d[x2][y2][y] + G[x][y] + 1 + (x != y));
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

ps:本比赛模板代码

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <ctime>
#include <set>
using namespace std;

#define fs first
#define sc second
#define pb push_back
typedef pair<int, int> pii;
typedef double db;
typedef long long ll;
typedef long double ldb;
typedef unsigned long long ull;

原文地址:https://www.cnblogs.com/hongzy/p/12307242.html

时间: 2024-10-07 18:16:13

Codeforces Round #619 (Div. 2) 简要题解的相关文章

Codeforces Round #483 (Div. 1) 简要题解

来自FallDream的博客,未经允许,请勿转载,谢谢. 为了证明一下我又来更新了,写一篇简要的题解吧. 这场比赛好像有点神奇,E题莫名是道原题,导致有很多选手直接过掉了(Claris 表演24s过题).然而D题比E题要难一些,分还少. A. Finite or not? 先把\(\frac{p}{q}\)约成最简分数,然后就是要判断是否\(q\)的所有质因数都是\(b\)的质因数. 每次取\(g=gcd(b,q)\),并尽可能的让\(q\)除\(g\),最后判断\(q\)是否是1即可. 还有一

Codeforces Round #498 (Div. 3) 简要题解

[比赛链接] https://codeforces.com/contest/1006 [题解] Problem A. Adjacent Replacements        [算法] 将序列中的所有偶数替换为奇数即可 时间复杂度 : O(N) [代码] #include<bits/stdc++.h> using namespace std; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y);

# Codeforces Round #529(Div.3)个人题解

Codeforces Round #529(Div.3)个人题解 前言: 闲来无事补了前天的cf,想着最近刷题有点点怠惰,就直接一场cf一场cf的刷算了,以后的题解也都会以每场的形式写出来 A. Repeating Cipher 传送门 题意:第一个字母写一次,第二个字母写两次,依次递推,求原字符串是什么 题解:1.2.3.4,非常明显的d=1的等差数列,所以预处理一个等差数列直接取等差数列的每一项即可 代码: #include<bits/stdc++.h> using namespace s

Codeforces Round #619 (Div. 2) Ayoub&#39;s function

Ayoub thinks that he is a very smart person, so he created a function f(s)f(s) , where ss is a binary string (a string which contains only symbols "0" and "1"). The function f(s)f(s) is equal to the number of substrings in the string s

Codeforces Round #531 (Div. 3) ABCDE题解

Codeforces Round #531 (Div. 3) 题目总链接:https://codeforces.com/contest/1102 A. Integer Sequence Dividing 题意: 给一个数n,然后要求你把1,2.....n分为两个集合,使得两个集合里面元素的和的差的绝对值最小. 题解: 分析可以发现,当n%4==0 或者 n%3==0,答案为0:其余答案为1.之后输出一下就好了. 代码如下: #include <bits/stdc++.h> using name

Codeforces Round #540 (Div. 3) 部分题解

Codeforces Round #540 (Div. 3) 题目链接:https://codeforces.com/contest/1118 题目太多啦,解释题意都花很多时间...还有事情要做,就选一些题来写吧. B. Tanya and Candies 题意: 在n个数中任意删去一个,如果这个数被删去后,剩余数的奇数和以及偶数和相等,那么就定义这个数为"好数".现在问这n个数中有多少个“好数”. 题解: 预处理出奇数前缀和.偶数前缀和,删去一个数后所有的奇数位置和 就为前面的奇数和

Codeforces Round #632 (Div. 2) 部分题解

目录 Codeforces Round #632 (Div. 2) A. Little Artem B. Kind Anton C. Eugene and an array D. Challenges in school №41 F. Kate and imperfection Codeforces Round #632 (Div. 2) A. Little Artem 题意:略. 分析:构造这样的图形: BWW...W BWW...W BBB...B #include <bits/stdc++

Codeforces Round #Pi (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/567 听说Round #Pi的意思是Round #314... A. Lineland Mail time limit per test:3 seconds memory limit per test:256 megabytes All cities of Lineland are located on the Ox coordinate axis. Thus, each city is associated with it

Codeforces Round #200 (Div. 2) (ABCDE题解)

比赛链接:http://codeforces.com/contest/344 A. Magnets time limit per test:1 second memory limit per test:256 megabytes Mad scientist Mike entertains himself by arranging rows of dominoes. He doesn't need dominoes, though: he uses rectangular magnets inst