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;

猜你喜欢

转载自www.cnblogs.com/hongzy/p/12307242.html