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;
}
淦!
这么水的一个题, 我居然写了这么久...
看不见我看不见我看不见我