C - X drawing Editorial by en_translator
First, consider which squares are painted by the first operation:
- for every integer \(k\) such that \(\max(1-A,1-B)\leq k\leq \min(N-A,N-B)\), paint \((A+k,B+k)\) black.
If we try to naively simulate this, there will be at most \(10^{18}\) squares to be painted, which is too enormous to finish in time. So we consider rephrasing this condition. First, this is equivalent to:
- for every integer such that \(1-A\leq k \leq N-A\) and \(1-B \leq k \leq N-B\), paint \((A+k,B+k)\) black.
Therefore, it is rephrase to:
- for every integer such that \(1\leq A+k \leq N\) and \(1 \leq B+k \leq N\), paint \((A+k,B+k)\) black.
What we want to know is in the range of \(P\leq i \leq Q\) and \(R\leq j \leq S\), and by \(1\leq P\leq Q \leq N\) and \(1\leq R\leq S \leq N\), so this operation can be replaced with
- for every integer such that \(P\leq A+k \leq Q\) and \(R \leq B+k \leq S\), paint \((A+k,B+k)\) black
without changing the answer. By transforming back by the inverse operation of the discussion above, we can say that
- for every integer \(k\) such that \(\max(P-A,R-B)\leq k\leq \min(Q-A,S-B)\), paint \((A+k,B+k)\) black.
We can similarly rephrase the second operation too:
- for every integer \(k\) such that \(\max(1-A,B-N)\leq k\leq \min(N-A,B-1)\), paint \((A+k,B-k)\) black
can be replaced with
- for every integer \(k\) such that \(\max(P-A,B-S)\leq k\leq \min(Q-A,B-R)\), paint \((A+k,B-k)\) black.
Now, we consider simulating these operations. Each operation is performed at most \(\min(Q-P+1,S-R+1)\) time, which is obviously at most \(3\times 10^5\). (Actually the evaluation can be stricter: we can say that it is no more than \([\sqrt{300000}]=547\).)
Therefore, this simulation can be done in the time limit, so the problem has been solved. In some programming languages like C++, if you store the range to be simulated with a fixed-size, it will need a size of \(300000\times 300000\), which will exceed the memory limit.
Another solution
In the explanation above, the first operation was rephrased as follows:
- for every integer \(k\) such that \(1\leq A+k \leq N\) and \(1 \leq B+k \leq N\) , paint \((A+k,B+k)\) black.
This can be further reworded as:
- for every pair of integers \((i,j)\) such that \(1\leq i \leq N\), \(1 \leq j \leq N\), and \(i-j=A-B\), paint \((i,j)\) black.
Similarly, the second operation is equivalent to:
- for every pair of integers \((i,j)\) such that \(1\leq i \leq N\), \(1 \leq j \leq N\), and \(i+j=A+B\), paint \((i,j)\) black.
By using these facts, we may solve this problem in the following alternative way: for each \((i,j)\) such that \(P\leq i\leq Q\) and \(R\leq j\leq S\), check if \(i-j=A-B\) or \(i+j=A+B\), and if it holds, output #
, or it doesn’t, output .
. This simplifies the implementation a bit.
Sample code in C++:
#include <bits/stdc++.h>
using namespace std;
int main(void) {
long long n, a, b;
long long p, q, r, s;
long long x, y;
string str = "";
vector<string>ans;
cin >> n >> a >> b;
cin >> p >> q >> r >> s;
for (long long i = 0; i < (s - r + 1); i++)str += '.';
for (long long i = 0; i < (q - p + 1); i++)ans.push_back(str);
x = max(p - a, r - b);
y = min(q - a, s - b);
for (long long i = x; i <= y; i++)ans[a + i - p][b + i - r] = '#';
x = max(p - a, b - s);
y = min(q - a, b - r);
for (long long i = x; i <= y; i++)ans[a + i - p][b - i - r] = '#';
for (long long i = 0; i < (q - p + 1); i++)cout << ans[i] << endl;
return 0;
}
Sample code of the alternative solution (C++):
#include <bits/stdc++.h>
using namespace std;
int main(void) {
long long n, a, b;
long long p, q, r, s;
cin >> n >> a >> b;
cin >> p >> q >> r >> s;
for (long long i = p; i <= q; i++) {
for (long long j = r; j <= s; j++) {
if ((i - j) == (a - b))cout << '#';
else if ((i + j) == (a + b))cout << '#';
else cout << ".";
}
cout << endl;
}
return 0;
}
posted:
last update: