CF1301E Nanosoft

CF1301E Nanosoft

一道大水题, 燃鹅我写了一天, 日...

思路非常简单, 就是处理出每个 \(logo\) 大小, 然后用二维 \(ST\) 表维护, \(O(n^3)\) 预处理, \(O(n^2 \log n)\) 处理 \(ST\) , \(O(1)\) 查询, 为了便于操作, 这里取每一个红块的右下角作为这个 \(logo\) 的代言人.

然后写了半天, 一直输出 \(0\) ...后来一通乱搞, 写了个暴力.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) +(ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 505;
int n, m, q, R[N][N], G[N][N], B[N][N], Y[N][N], S[N][N], RS[N][N], GS[N][N], BS[N][N], YS[N][N];
void init() {
    n = read(), m = read(), q = read();
    for (int i = 1; i <= n; i++) {
        char ch;
        for (int j = 1; j <= m; j++) {
            ch = getchar();
            R[i][j] = R[i - 1][j] + R[i][j - 1] - R[i - 1][j - 1];
            G[i][j] = G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
            B[i][j] = B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
            Y[i][j] = Y[i - 1][j] + Y[i][j - 1] - Y[i - 1][j - 1];
            if (ch == 'R') R[i][j]++;
            else if (ch == 'G') G[i][j]++;
            else if (ch == 'B') B[i][j]++;
            else Y[i][j]++;
        }
        ch = getchar();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (R[i][j] + R[i - l][j - l] - R[i][j - l] - R[i - l][j] == l * l && i - l >= 0 && j - l >= 0) l++;
            RS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            i--, j++;
            while (G[i][j + l] + G[i - l][j] - G[i][j] - G[i - l][j + l] == l * l && i + l <= n && j - l >= 0) l++;
            GS[i][j] = l - 1;
            i++, j--;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (B[i + l][j + l] + B[i][j] - B[i][j + l] - B[i + l][j] == l * l && i + l <= n && j + l <= m) l++;
            BS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            i++, j--;
            while (Y[i + l][j] + Y[i][j - l] - Y[i][j] - Y[i + l][j - l] == l * l && i - l >= 0 && j + l <= m) l++;
            YS[i][j] = l - 1;
            i--, j++;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            S[i][j] = min(RS[i][j], min(GS[i][j], min(BS[i][j], YS[i][j])));
        }
    }
}
void Query(int x, int y, int xx, int yy) {
    int ans = 0;
    for (int i = x; i <= xx; i++) {
        for (int j = y; j <= yy; j++) {
            int l = min(i - x + 1, min(j - y + 1, min(xx - i, yy - j)));
            ans = max(ans, min(S[i][j], l));
        }
    }
    printf("%d\n", ans * ans * 4);
}
int main() {
    init();
    while (q--) {
        int i = read(), j = read(), k = read(), l = read();
        Query(i, j, k, l);
    }
    return 0;
}

给下标一通乱加减, 然后把样例*过去了, 结果 \(WA\ on\ test\ 8\) , 挺好.

然后不知道咋想的, 明明是 \(WA\) 了, 但是却去写 \(ST\) 了...

结果可想而知...

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) +(ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 505;
int n, m, q, R[N][N], G[N][N], B[N][N], Y[N][N], S[N][N], RS[N][N], GS[N][N], BS[N][N], YS[N][N], f[N][N][12][12], Log[N];
void init() {
    n = read(), m = read(), q = read();
    Log[0] = -1;
    for (int i = 1; i <= n || i <= m; i++) Log[i] = Log[i >> 1] + 1;
    for (int i = 1; i <= n; i++) {
        char ch;
        for (int j = 1; j <= m; j++) {
            ch = getchar();
            R[i][j] = R[i - 1][j] + R[i][j - 1] - R[i - 1][j - 1];
            G[i][j] = G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
            B[i][j] = B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
            Y[i][j] = Y[i - 1][j] + Y[i][j - 1] - Y[i - 1][j - 1];
            if (ch == 'R') R[i][j]++;
            else if (ch == 'G') G[i][j]++;
            else if (ch == 'B') B[i][j]++;
            else Y[i][j]++;
        }
        ch = getchar();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (R[i][j] + R[i - l][j - l] - R[i][j - l] - R[i - l][j] == l * l && i - l >= 0 && j - l >= 0) l++;
            RS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1; i--, j++;
            while (G[i][j + l] + G[i - l][j] - G[i][j] - G[i - l][j + l] == l * l && i + l <= n && j - l >= 0) l++;
            GS[i][j] = l - 1; i++, j--;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (B[i + l][j + l] + B[i][j] - B[i][j + l] - B[i + l][j] == l * l && i + l <= n && j + l <= m) l++;
            BS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1; i++, j--;
            while (Y[i + l][j] + Y[i][j - l] - Y[i][j] - Y[i + l][j - l] == l * l && i - l >= 0 && j + l <= m) l++;
            YS[i][j] = l - 1; i--, j++;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            S[i][j] = min(min(RS[i][j], GS[i][j]), min(BS[i][j], YS[i][j]));
            if (S[i][j]) f[i][j][0][0] = S[i][j];
        }
    }
    for (int k = 0; k <= Log[n]; k++) {
        for (int l = 0; l <= Log[m]; l++) {
            if (!k && !l) continue;
            for (int i = 1; i + (1 << k) - 1 <= n; i++) {
                for (int j = 1; j + (1 << l) - 1 <= m; j++) {
                    f[i][j][k][l] = l ? max(f[i][j][k][l - 1], f[i][j + (1 << l - 1)][k][l - 1]) : max(f[i][j][k - 1][l], f[i + (1 << k - 1)][j][k - 1][l]);
                }
            }
        }
    }
}
bool Check(int x, int y, int xx, int yy, int k) {
    int ans = 0, Lx = Log[xx - x + 1], Ly = Log[yy - y + 1];
    ans = max(max(f[x][y][Lx][Ly], f[xx - (1 << Lx) + 1][yy - (1 << Ly) + 1][Lx][Ly]), max(f[xx - (1 << Lx) + 1][y][Lx][Ly], f[x][yy - (1 << Ly) + 1][Lx][Ly]));
    return k <= ans;
}
int Binary_Ans(int x, int y, int xx, int yy, int k) {
    int l = 0, r = k, mid, ans = 0;
    while (l <= r) {
        mid = l + r + 1 >> 1;
        if (Check(x, y, xx, yy, mid)) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    return ans;
}
void Solve(int x, int y, int xx, int yy) {
    int l = min(xx - x + 1, yy - y + 1) >> 1, ans = 0, tmp;
    for (int i = 1; i <= l; i++) {
        tmp = Binary_Ans(x + i - 1, y + i - 1, xx - i, yy - i, i);
        ans = max(ans, tmp);
    }
    printf("%d\n", ans * ans * 4);
}
int main() {
    init();
    while (q--) {
        int x = read(), y = read(), xx = read(), yy = read();
        Solve(x, y, xx, yy);
    }
    return 0;
}

漂亮!!!

我就知道, 又 \(WA\) 了, 然后就干脆改代码, 成了下面这样.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) +(ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 505;
int n, m, q, R[N][N], G[N][N], B[N][N], Y[N][N], f[N][N][12][12], Log[N];
bool Judge(int i, int j, int l) {
    if (R[i][j] - R[i][j - l] - R[i - l][j] + R[i - l][j - l] < l * l) return false;
    if (G[i][j + l] - G[i][j] - G[i - l][j + l] + G[i - l][j] < l * l) return false;
    if (B[i + l][j + l] - B[i][j + l] - B[i + l][j] + B[i][j] < l * l) return false;
    if (Y[i + l][j] - Y[i][j] - Y[i + l][j - l] + Y[i][j - l] < l * l) return false;
    return true;
}
void init() {
    n = read(), m = read(), q = read();
    Log[0] = -1;
    for (int i = 1; i <= n || i <= m; i++) Log[i] = Log[i >> 1] + 1;
    for (int i = 1; i <= n; i++) {
        char ch;
        for (int j = 1; j <= m; j++) {
            ch = getchar();
            R[i][j] = R[i - 1][j] + R[i][j - 1] - R[i - 1][j - 1];
            G[i][j] = G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
            B[i][j] = B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
            Y[i][j] = Y[i - 1][j] + Y[i][j - 1] - Y[i - 1][j - 1];
            if (ch == 'R') R[i][j]++;
            else if (ch == 'G') G[i][j]++;
            else if (ch == 'B') B[i][j]++;
            else Y[i][j]++;
        }
        ch = getchar();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (Judge(i, j, l) && i - l >= 0 && j - l >= 0 && i + l <= n && j + l <= m) l++;
            f[i][j][0][0] = l - 1;
        }
    }
    for (int k = 0; k <= Log[n]; k++) {
        for (int l = 0; l <= Log[m]; l++) {
            if (!k && !l) continue;
            for (int i = 1; i + (1 << k) - 1 <= n; i++) {
                for (int j = 1; j + (1 << l) - 1 <= m; j++) {
                    f[i][j][k][l] = l ? max(f[i][j][k][l - 1], f[i][j + (1 << l - 1)][k][l - 1]) : max(f[i][j][k - 1][l], f[i + (1 << k - 1)][j][k - 1][l]);
                }
            }
        }
    }
}
bool Check(int x, int y, int xx, int yy, int k) {
    int ans = 0, Lx = Log[xx - x + 1], Ly = Log[yy - y + 1];
    ans = max(max(f[x][y][Lx][Ly], f[xx - (1 << Lx) + 1][yy - (1 << Ly) + 1][Lx][Ly]), max(f[xx - (1 << Lx) + 1][y][Lx][Ly], f[x][yy - (1 << Ly) + 1][Lx][Ly]));
    return k <= ans;
}
int Binary_Ans(int x, int y, int xx, int yy, int k) {
    int l = 0, r = k, mid, ans = 0;
    while (l <= r) {
        mid = l + r + 1 >> 1;
        if (Check(x, y, xx, yy, mid)) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    return ans;
}
void Solve(int x, int y, int xx, int yy) {
    int l = min(xx - x + 1, yy - y + 1) >> 1, ans = 0, tmp;
    for (int i = 1; i <= l; i++) {
        tmp = Binary_Ans(x + i - 1, y + i - 1, xx - i, yy - i, i);
        ans = max(ans, tmp);
    }
    printf("%d\n", ans * ans * 4);
}
int main() {
    init();
    while (q--) {
        int x = read(), y = read(), xx = read(), yy = read();
        Solve(x, y, xx, yy);
    }
    return 0;
}

过样例了?!!!没 \(WA\) !!!, 居然是 \(TLE\) , 日...

我这没乱加减怎么就过样例了...

嘶~, 居然是 \(G\)\(Y\) 写反了, 日...

改完了, 不乱搞的老代码.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) +(ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 505;
int n, m, q, R[N][N], G[N][N], B[N][N], Y[N][N], S[N][N], RS[N][N], GS[N][N], BS[N][N], YS[N][N], f[N][N][12][12], Log[N];
void init() {
    n = read(), m = read(), q = read();
    Log[0] = -1;
    for (int i = 1; i <= n || i <= m; i++) Log[i] = Log[i >> 1] + 1;
    for (int i = 1; i <= n; i++) {
        char ch;
        for (int j = 1; j <= m; j++) {
            ch = getchar();
            R[i][j] = R[i - 1][j] + R[i][j - 1] - R[i - 1][j - 1];
            G[i][j] = G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
            B[i][j] = B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
            Y[i][j] = Y[i - 1][j] + Y[i][j - 1] - Y[i - 1][j - 1];
            if (ch == 'R') R[i][j]++;
            else if (ch == 'G') G[i][j]++;
            else if (ch == 'B') B[i][j]++;
            else Y[i][j]++;
        }
        ch = getchar();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (R[i][j] + R[i - l][j - l] - R[i][j - l] - R[i - l][j] == l * l && i - l >= 0 && j - l >= 0) l++;
            RS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (G[i][j + l] + G[i - l][j] - G[i][j] - G[i - l][j + l] == l * l && i + l <= n && j - l >= 0) l++;
            GS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (B[i + l][j + l] + B[i][j] - B[i][j + l] - B[i + l][j] == l * l && i + l <= n && j + l <= m) l++;
            BS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (Y[i + l][j] + Y[i][j - l] - Y[i][j] - Y[i + l][j - l] == l * l && i - l >= 0 && j + l <= m) l++;
            YS[i][j] = l - 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            S[i][j] = min(min(RS[i][j], GS[i][j]), min(BS[i][j], YS[i][j]));
            if (S[i][j]) f[i][j][0][0] = S[i][j];
        }
    }
    for (int k = 0; k <= Log[n]; k++) {
        for (int l = 0; l <= Log[m]; l++) {
            if (!k && !l) continue;
            for (int i = 1; i + (1 << k) - 1 <= n; i++) {
                for (int j = 1; j + (1 << l) - 1 <= m; j++) {
                    f[i][j][k][l] = l ? max(f[i][j][k][l - 1], f[i][j + (1 << l - 1)][k][l - 1]) : max(f[i][j][k - 1][l], f[i + (1 << k - 1)][j][k - 1][l]);
                }
            }
        }
    }
}
bool Check(int x, int y, int xx, int yy, int k) {
    int ans = 0, Lx = Log[xx - x + 1], Ly = Log[yy - y + 1];
    ans = max(max(f[x][y][Lx][Ly], f[xx - (1 << Lx) + 1][yy - (1 << Ly) + 1][Lx][Ly]), max(f[xx - (1 << Lx) + 1][y][Lx][Ly], f[x][yy - (1 << Ly) + 1][Lx][Ly]));
    return k <= ans;
}
int Binary_Ans(int x, int y, int xx, int yy, int k) {
    int l = 0, r = k, mid, ans = 0;
    while (l <= r) {
        mid = l + r + 1 >> 1;
        if (Check(x, y, xx, yy, mid)) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    return ans;
}
void Solve(int x, int y, int xx, int yy) {
    int l = min(xx - x + 1, yy - y + 1) >> 1, ans = 0, tmp;
    for (int i = 1; i <= l; i++) {
        tmp = Binary_Ans(x + i - 1, y + i - 1, xx - i, yy - i, i);
        ans = max(ans, tmp);
    }
    printf("%d\n", ans * ans * 4);
}
int main() {
    init();
    while (q--) {
        int x = read(), y = read(), xx = read(), yy = read();
        Solve(x, y, xx, yy);
    }
    return 0;
}

芜湖~, 这才对嘛...

好了, 心满意足了.

调新代码去, 老代码太冗了(老代码: 日!那你改我干嘛.).

突然发现!我的查询不是 \(O(1)\) , 而是 \(O(n \log n)\) ...日...

稍作修改.

好了, 也短了, 也快了.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) +(ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 505;
int n, m, q, R[N][N], G[N][N], B[N][N], Y[N][N], f[N][N][12][12], Log[N];
bool Judge(int i, int j, int l) {
    if (R[i][j] - R[i][j - l] - R[i - l][j] + R[i - l][j - l] < l * l) return false;
    if (G[i][j + l] - G[i][j] - G[i - l][j + l] + G[i - l][j] < l * l) return false;
    if (B[i + l][j + l] - B[i][j + l] - B[i + l][j] + B[i][j] < l * l) return false;
    if (Y[i + l][j] - Y[i][j] - Y[i + l][j - l] + Y[i][j - l] < l * l) return false;
    return true;
}
void init() {
    n = read(), m = read(), q = read();
    Log[0] = -1;
    for (int i = 1; i <= n || i <= m; i++) Log[i] = Log[i >> 1] + 1;
    for (int i = 1; i <= n; i++) {
        char ch;
        for (int j = 1; j <= m; j++) {
            ch = getchar();
            R[i][j] = R[i - 1][j] + R[i][j - 1] - R[i - 1][j - 1];
            G[i][j] = G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
            B[i][j] = B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
            Y[i][j] = Y[i - 1][j] + Y[i][j - 1] - Y[i - 1][j - 1];
            if (ch == 'R') R[i][j]++;
            else if (ch == 'G') G[i][j]++;
            else if (ch == 'B') B[i][j]++;
            else Y[i][j]++;
        }
        ch = getchar();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int l = 1;
            while (Judge(i, j, l) && i - l >= 0 && j - l >= 0 && i + l <= n && j + l <= m) l++;
            f[i][j][0][0] = l - 1;
        }
    }
    for (int k = 0; k <= Log[n]; k++) {
        for (int l = 0; l <= Log[m]; l++) {
            if (!k && !l) continue;
            for (int i = 1; i + (1 << k) - 1 <= n; i++) {
                for (int j = 1; j + (1 << l) - 1 <= m; j++) {
                    f[i][j][k][l] = l ? max(f[i][j][k][l - 1], f[i][j + (1 << l - 1)][k][l - 1]) : max(f[i][j][k - 1][l], f[i + (1 << k - 1)][j][k - 1][l]);
                }
            }
        }
    }
}
bool Check(int x, int y, int xx, int yy, int k) {
    int ans = 0, Lx = Log[xx - x + 1], Ly = Log[yy - y + 1];
    ans = max(max(f[x][y][Lx][Ly], f[xx - (1 << Lx) + 1][yy - (1 << Ly) + 1][Lx][Ly]), max(f[xx - (1 << Lx) + 1][y][Lx][Ly], f[x][yy - (1 << Ly) + 1][Lx][Ly]));
    return k <= ans;
}
void Solve(int x, int y, int xx, int yy) {
    int l = 0, r = min(xx - x + 1, yy - y + 1) >> 1, mid, ans;
    while (l <= r) {
        mid = l + r >> 1;
        if (Check(x + mid - 1, y + mid - 1, xx - mid, yy - mid, mid)) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    printf("%d\n", ans * ans * 4);
}
int main() {
    init();
    while (q--) {
        int x = read(), y = read(), xx = read(), yy = read();
        Solve(x, y, xx, yy);
    }
    return 0;
}

淦!

这么水的一个题, 我居然写了这么久...

posted @ 2021-08-22 20:10  sshadows  阅读(30)  评论(0编辑  收藏  举报