### chokudai's blog

By chokudai, history, 2 months ago,

We will hold AtCoder Beginner Contest 210.

The point values will be 100-200-300-400-500-600.

We are looking forward to your participation!

• +88

 » 2 months ago, # |   0 Thanks for the wonderful contest! I spent a lot of time on D. Wish I was faster with implementation skills got it in like last 2 minutes phew! D-ideaExpand the manhattan distance and make 4 cases, 2 of which will be redundant. So we need 2 dp's to calculate answer. Code//Think simple yet elegant. //Keep your brain open. #include using namespace std; #define fast ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); #define ll long long #define all(v) v.begin(),v.end() #define F first #define S second #define pb push_back #define mp make_pair #define pi pair #define pii pair #define REP(i,n) for(int i=0;i(chrono::high_resolution_clock::now() - blockTime.first).count()), blockTime.second = false \ ) struct dat{ ll cost,x,y; }; void run_case(){ ll h,w,x,c; ll i,j; cin >> h >> w >> c; ll g[h][w]; for(i=0;i> g[i][j]; } } ll ans = 1e18,fans=1e18; ll dp1[h][w],dp2[h][w]; for(i=0;i=0;--j){ if(i>0 && j0 && j==w-1){ dp1[i][j]=dp1[i-1][j]; ans=min(ans,dp1[i][j]+g[i][j]+c*(i+1-j-1)); dp1[i][j]=min(dp1[i][j],g[i][j]-c*(i+1-j-1)); } if(i==0 && j==w-1) dp1[i][j]=g[i][j]-c*(i+1-j-1); } } for(i=h-1;i>=0;--i){ for(j=w-1;j>=0;--j){ if(i
•  » » 2 months ago, # ^ |   +1 Instead of making 4 cases, just make 2 cases. Lets just fix the point for which 'row' value would be bigger. The code gets a lot more simple with that. Codevoid testCase() { int n, m, k; cin >> n >> m >> k; vector pmi(m + 1, inf), smi(m + 2, inf); int a[n + 1][m + 1]; int ans = inf; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; pmi[j] = min(pmi[j], pmi[j - 1]); int c1 = a[i][j] + k * (i + j) + pmi[j]; int c2 = a[i][j] + k * (i - j) + smi[j]; ans = min({ans, c1, c2}); pmi[j] = min({pmi[j], a[i][j] - k * (i + j)}); } for (int j = m; j > 0; j--) smi[j] = min({smi[j], smi[j + 1], a[i][j] + k * (j - i)}); } cout << ans; } 
•  » » » 2 months ago, # ^ | ← Rev. 2 →   0 Yeah I have made 2 cases not 4. But your's is much neat :)
•  » » » » 2 months ago, # ^ |   0 Can you explain the idea slightly more?
•  » » » » » 2 months ago, # ^ | ← Rev. 2 →   0 The 1st and 4th quadrants are what we need to calculate answer(the other 2 are symmetric to 1 and 4 so we can discard them.). So consider them only and write expression of cost. It will of form $A[i][j]\pm c*(i\pm j) + A[i'][j']\pm c*(i'\pm j')$We treat each half individually and do a dp on the later half and store its minimum value over some 2d prefix matrix. Then we check and try to improve our answer by adding the former part of the expression and print the minimum.
•  » » 2 months ago, # ^ |   0 A short implementation - Submission
•  » » » 2 months ago, # ^ |   0 How to think of short implementations faster ?
•  » » » » 2 months ago, # ^ |   0 Think of some tricks to simulate many cases with some variables which you can pass in some function on basis of which it will change. Don't know to explain it better.
•  » » 2 months ago, # ^ |   0 Can you plz. explain problem c ?
 » 2 months ago, # |   +31 How to do F?
•  » » 2 months ago, # ^ |   -14 ++
•  » » 2 months ago, # ^ | ← Rev. 2 →   +3 represent inputs by their prime factors cry... edit: editorial's out, I wasn't nearly as close as I'd guessed
•  » » 2 months ago, # ^ |   +15 We can reduce the problem to one big 2-SAT instance, containing one variable per card denoting which side of it we use (plus some supplementary ones). First, we go through every possible divisor $d \in [2, MAX]$, where $MAX = 2 \cdot 10^6$, that could divide two numbers on the front side of two cards. For every $d$, we enumerate all cards $C_d$ that contain a number divisible by $d$ on either side. We can to this in $\mathcal{O}(MAX \log MAX)$ if we save every card containing a number for every number. The total size of all $C_d$ should be roughly $4 \cdot 10^6$ if we use the $\sqrt[3]{n}$ approximation for the number of divisors of some $n$.Now for every $d$, we check whether there exists a card containing numbers divisible by $d$ on both sides. If thats the case, we go through we all other cards in $C_d$ and force them be flipped to the side not divisible by $d$ using a clause like $(x \lor x)$ or $(\overline{x} \lor \overline{x})$ (if there is another card with both sides divisible by $d$, we can immediately output no).If there is no card with both sides divisible by $d$, we want to allow at most one card in $C_d$ to be flipped to its divisible-by-$d$ side. For that there is a construction using about $3 \lvert C_d \rvert$ clauses and $\lvert C_d \rvert$ supplementary variables. KACTL's 2-SAT code contains an implementation for it. I've always used it without figuring out why it works, but it probably becomes obvious if you spend some time playing around with it on paper. Solving the 2-SAT instance then just requires the standard algorithm using strongly-connected components.
•  » » » 2 months ago, # ^ |   +5 For the last paragraph, you mentioned I used edges in a kind of prefix and suffix order a little bit similar to this Problem.Is there any other nice trick to handle these types of implications? mine implementation was messy.
 » 2 months ago, # |   0 How to solve E?
•  » » 2 months ago, # ^ |   +6 Make pair of $Ai$ and $Cost$. Sort on Cost in ascending order, if cost is same compare gcd($Ai$,$N$). Calculate final answer by iterating on the vector pair and adding maximum possible edges with the current cost (edges = $N$ — $gcd(N-Ai)$). Update $N$ = $gcd$ after every iteration. If we reach $n$ = 1, i.e we made N-1 edges, break.
•  » » » 2 months ago, # ^ | ← Rev. 2 →   0 Actually this explanation is very helpful. I should just draw out some simple examples I guess to understand it. I've never seen any problems like it. What kind of prerequisite is helpful to get this one? The editorial just left me in the dust. I know modular arithmetic for the most part, but don't know how gcd came into it.
 » 2 months ago, # |   0 My code for D was failing for only 3 testcases for some reason. Can someone tell what is wrong with my code? Submission Link Code#include #define int int64_t using namespace std; const int N = 1e3+69; int A[N][N], dp[N][N]; int32_t main() { ios_base::sync_with_stdio(0); cin.tie(0); int h, w, c; cin >> h >> w >> c; for(int i = 1; i <= h; i++) for(int j = 1; j <= w; j++) cin >> A[i][j]; int ans = dp[1][1] = 1e18; for(int i = 2; i <= h; i++) dp[i][1] = c + min(dp[i - 1][1] + A[i][1] - A[i - 1][1], A[i][1] + A[i - 1][1]), ans = min(ans, dp[i][1]); for(int j = 2; j <= w; j++) dp[1][j] = c + min(dp[1][j - 1] + A[1][j] - A[1][j - 1], A[1][j] + A[1][j - 1]), ans = min(ans, dp[1][j]); for(int i = 2; i <= h; i++) for(int j = 2; j <= w; j++) { dp[i][j] = c + min(dp[i - 1][j] + A[i][j] - A[i - 1][j], A[i][j] + A[i - 1][j]); dp[i][j] = min(dp[i][j], c + min(dp[i][j - 1] + A[i][j] - A[i][j - 1], A[i][j] + A[i][j - 1])); ans = min(ans, dp[i][j]); } cout << ans; } 
•  » » 2 months ago, # ^ | ← Rev. 2 →   0 .
•  » » 2 months ago, # ^ | ← Rev. 3 →   +3 Try this case 2 2 1 13 1 1 13 The answer should be $4$. $(1, 2)$ and $(2, 1)$I also made the same mistake, you can correct it by rotating the grid clockwise once and repeating the dp.
•  » » » 2 months ago, # ^ |   0 thanks
•  » » 2 months ago, # ^ |   +1 I made the same mistake 5 times :(We are only checking for (i, j) and (i', j'), such that (i, j) is up and left when compared to (i', j'). There need to be two DP checks for both directions.
•  » » 2 months ago, # ^ | ← Rev. 2 →   0 Deleted
 » 2 months ago, # |   +3 difficulty gap between C & D is soo high!
•  » » 2 months ago, # ^ |   0 So true..
 » 2 months ago, # |   +8 Wrote some hell on D, E was easier
 » 2 months ago, # |   +19 A different idea to solve D: Let's solve it as a shortest paths problem. The graph will have a start vertex, which is connected to some randomly chosen tiles in the grid. The rest of the tiles is connected to the end vertex. Then search for the shortest path from start vertex to end vertex.More concretely, from the start vertex make an edge of length $A_{i,j}$ to some pairs $(i, j)$ and from some pairs $(i', j')$ have an edge of length $A_{i',j'}$ to the end vertex. Also connect each $(i, j)$ to neighboring tiles ($(i + 1, j), (i - 1, j), (i, j+1), (i, j-1)$) with length $C$.We set the probability of being connected to the start vertex as 0.5. The probability that the optimal pair has one vertex connected to the start and the other to the end is also 0.5. So if we repeat this whole algorithm $k$ times, the probability that we missed the optimal pair is just $2^{-k}$. Admitedly, this has a worse complexity than the solution in the editorial, $O(WH * log(WH) * k)$
 » 2 months ago, # |   +9 Can someone explain problem E solution. I am not able to understand how they are calculating the number of connected components after each operation in the editorial.
•  » » 2 months ago, # ^ |   +6 ++
 » 2 months ago, # |   0 Can anyone give me the solution of problem D according to tutorial logic?
 » 3 weeks ago, # | ← Rev. 2 →   0 Can anybody take a look at my code!? This is a O(H * W * log(H + W)) solution, but getting TLE on few cases. Is there a way to make it more efficient? Here's my Code.#include using namespace std; typedef long long ll; ll mn(vector> &grid, ll c) { int h = grid.size(), w = grid[0].size(); set>> val; for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) val.insert({grid[i][j] + c * (i + j), {i, j}}); int i = 0; vector> q = {{0, 0}}; ll mn_poss = 1e15; int l = h + w - 1; while (i < l) { vector> temp; if (q[0].first < h - 1) temp.push_back({q[0].first + 1, q[0].second}); for (int j = 0; j < q.size(); j++) { val.erase({grid[q[j].first][q[j].second] + c * i, {q[j].first, q[j].second}}); int m = q[j].first, n = q[j].second; if (n < w - 1) temp.push_back({m, n + 1}); } while (!q.empty() && !val.empty()) { auto mn = q.back(); q.pop_back(); auto xx = *val.begin(); int u = mn.first, v = mn.second; int w = xx.second.first, x = xx.second.second; mn_poss = min(mn_poss, grid[w][x] + grid[u][v] + c * (abs(w - u) + abs(x - v))); } q = vector>(temp.begin(), temp.end()); i++; } return mn_poss; } vector> trans(vector> &grid) { int m = grid.size(), n = grid[0].size(); vector> ans(n, vector(m)); for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) ans[j][m - i - 1] = grid[i][j]; return ans; } void solve() { int h, w; ll c; cin >> h >> w >> c; vector> grid(h, vector(w)); for (auto &it : grid) for (auto &jt : it) cin >> jt; ll x = mn(grid, c); grid = trans(grid); ll y = mn(grid, c); cout << min(x, y) << "\n"; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int t = 1; while (t--) { solve(); } return 0; }