Submission #610095

#TimeUsernameProblemLanguageResultExecution timeMemory
610095jophyyjhVision Program (IOI19_vision)C++14
100 / 100
39 ms4540 KiB
/** * Wow. Idk how to express my shock when i saw that interactive problems can be like * this! So we basically have to write a program that outputs the correct 0/1 across * all images. First thought: we can't do compare each pair of rows, this takes about * 19900 (>10000) calls. * We don't have "for" or "if" statements... Hmm. I don't wanna do int addition / * subtraction using logic gates too... Well, in general we don't have much calls * available, so perhaps in a lot of calls the num of input isn't small. Nah... * * I'd like to note down my final thought. Suppose that c_1, c_2, ..., c_m are 0/1 * bits representing whether column i has a black cell. Let's put away the case of * only one 1. Let d_i := c_1 ^ c_2 ^ ... ^ c_i, so the number of 1s in (d_i) is * the horizontal dist. Similarly we can do this for the vertical direction, then * it suffices to count the num of 1s in some cells and check if it's K. * Unfortunately, the only sol i have is to do a dp which requires an additional * K(H+W) cells. Too much... (I'll submit a brute-force version in impl1) * * This think this is a problem where scoring partials is easy, but getting full is * hard. Tinjyu gave a hint during our IOI 2022 training: consider diagonals. Take * K=1 as an example. We know that if num of calls is O(HW) we definitely fail, but * if it's O(HW) we have a large const. factor to play with (since num of calls is * the bottleneck). So, take OR on each diagonal and take AND on adjacent diagonals. * Notice that if two cells' Manhattan dist. is 1, exactly 2 pairs of adjacent * diagonals have 1 in their ANDs. * * We can generalize this approach. Assume that the two cells are u, v. We draw two * diagonals through u and two diagonals through v; since in each direction there * are exactly 2 diagonals, the max of dist. between diagonals in the same direction * would be their Manhattan dist. I guess this may be inspired by the fact that cells * whose dist. to a fixed cell form the border of a rotated square. * This is so beautiful (!), though i can hardly believe that I would be able to come * up with sth like this! In some way, it's like rotating the grid by 45deg, * transforming Manhattan into Chebyschef. * * Number of calls: 5(H+W) (idk if 5 is correct, but it must be O(H+W)) * Number of reads: (idk, but not too many) * Implementation 1 (Solves [S1-3], [S5], [S6]) */ #include <bits/stdc++.h> #include "vision.h" typedef std::vector<int> vec; void construct_network(int h, int w, int K) { vec d1s, d2s; for (int d = 0; d <= h + w - 2; d++) { vec diag_cells; for (int i = 0; i < h; i++) { int j = d - i; if (0 <= j && j < w) diag_cells.push_back(i * w + j); } assert(!diag_cells.empty()); d1s.push_back(add_or(diag_cells)); } for (int d = -w + 1; d <= h - 1; d++) { vec diag_cells; for (int i = 0; i < h; i++) { int j = i - d; if (0 <= j && j < w) diag_cells.push_back(i * w + j); } assert(!diag_cells.empty()); d2s.push_back(add_or(diag_cells)); } int diags = h + w - 1; // We proceed in two parts. First checking whether the pairs in d1s and d2s // have dist. <= K, then we check whether there's one = K. vec greater_check; // should be all 0 for (int i = 0; i < diags; i++) { vec neighb1, neighb2; for (int j = 0; j < diags; j++) { int dist = std::abs(i - j); if (dist > K) { neighb1.push_back(d1s[j]); neighb2.push_back(d2s[j]); } } if (!neighb1.empty()) greater_check.push_back(add_and({add_or(neighb1), d1s[i]})); if (!neighb2.empty()) greater_check.push_back(add_and({add_or(neighb2), d2s[i]})); } int part1_flag; if (!greater_check.empty()) part1_flag = add_not(add_or(greater_check)); else part1_flag = -1; vec equal_check; for (int i = 0; i < diags; i++) { vec neighb1, neighb2; if (i + K < diags) { neighb1.push_back(d1s[i + K]); neighb2.push_back(d2s[i + K]); } if (i - K >= 0) { neighb1.push_back(d1s[i - K]); neighb2.push_back(d2s[i - K]); } if (!neighb1.empty()) equal_check.push_back(add_and({add_or(neighb1), d1s[i]})); if (!neighb2.empty()) equal_check.push_back(add_and({add_or(neighb2), d2s[i]})); } assert(!equal_check.empty()); int part2_flag = add_or(equal_check); // if part1_flag is -1 this is the ans if (part1_flag != -1) add_and({part1_flag, part2_flag}); // ans }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...