Блог пользователя chenjb

Автор chenjb, история, 5 лет назад, По-английски

Hello! I'm happy to announce XXII Open Cup: Grand Prix of Nanjing, which will be held on Dec 12th, 2021.

This contest is mainly prepared by SUA Programming Contest Problem Setter Team, which has already been used as the 2021 ICPC Asia Nanjing Regional Contest. There are around 700 teams participating in the Regional.

This is the fourth Nanjing Regional and the third Grand Prix of Nanjing in Open Cup, I feel very grateful and wish everyone enjoy this contest.

We also have an anonymous author this year. He provides a very interesting problem to this contest.

Authors: chenjb, TsReaper, jiangshibiao, shb123, quailty, Subconscious, oipotato

Testers: KAN, Um_nik, Merkurev, TLE, antontrygubO_o, heuristica, J.T.J.L., tun, sfiction, cxt, pb0207, Eden_CY, Suika_predator, lwn_16, lxlxl, xpchf, liyang21, AkaiLemon, nothing100, UESTC_Nocturne, Orenji.Sora, Gromah, smax, arvindr9, RandomKami

Contest link: https://official.contest.yandex.ru/opencupXXII/contest/33444/enter (Only visible for users with OpenCup login)

Open Cup Scoreboard: http://opentrains.snarknews.info/~ejudge/res/res10559

Regional Scoreboard: https://board.xcpcio.com/icpc/46th/nanjing

UPD: The contest is in the gym now.

  • Проголосовать: нравится
  • +107
  • Проголосовать: не нравится

»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by chenjb (previous revision, new revision, compare).

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

I Love ChenJB. :)

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +70 Проголосовать: не нравится

Thanks for the interesting problems!

How to solve problem L?

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +73 Проголосовать: не нравится

    Try to solve the problem assuming we may light/extinguish the central torch for each operation, then try to execute the same sequence by only lighting. While there are operations we can make, make them. In the end the remaining operations form consecutive groups, each of size 2. If there's an unlit torch next to such group, we can light it, do both operations in the group, then light it again, to the same effect. If all 2-groups are 1 apart, don't do anything as everything if fixed already.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +39 Проголосовать: не нравится

How to solve problem C? I tried dp on positions of x for every x that occures in the input but that approach gives WA7.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +31 Проголосовать: не нравится

How to solve J?

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +42 Проголосовать: не нравится

    Apply the solution of ABC231 Problem E on the divisibility graph of the factors of b-a.

    • »
      »
      »
      5 лет назад, скрыть # ^ |
       
      Проголосовать: нравится +49 Проголосовать: не нравится

      Sorry I don't quite understand. How do you bring down a to 1?

      • »
        »
        »
        »
        5 лет назад, скрыть # ^ |
        Rev. 2  
        Проголосовать: нравится +52 Проголосовать: не нравится

        I think what you basically construct is the following. Let $$$p_1, p_2, \dots, p_k$$$ be the sequence of primes you use to divide by in the reverse order: $$$p_1$$$ is the last prime to be divided by. Let $$$x_0$$$ be the balance of minus-plus operations you perform after you divide by every prime, $$$x_1$$$ be the balance of minus-plus operations before dividing by $$$p_1$$$ and so on.

        Then you should choose $$$x_0, x_1, \dots, x_k$$$ in such a way that $$$x_0 + p_1 \cdot x_1 + p_1 \cdot p_2 \cdot x_2 + \dots = a$$$ and $$$\sum\limits_{i=0}^{k} |x_i|$$$ is minimum possible.

        So to reduce to the ABC problem, you make the sequence of coins the sequence $$$1, p_1, p_1 \cdot p_2, \dots$$$. The only difference is that you forbid the transition to $$$\left\lfloor \frac a x \right\rfloor$$$ if it's equal to $$$0$$$. I guess it's never optimal to go to $$$0$$$ instead of $$$1$$$.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +62 Проголосовать: не нравится
pain
»
5 лет назад, скрыть # |
 
Проголосовать: нравится +26 Проголосовать: не нравится

I love statements taking INF time to load.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +26 Проголосовать: не нравится

How do solve D and H?

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +11 Проголосовать: не нравится

    H: Observe that if you enter a vertex $$$u$$$ for the first time, it can have at most two children from where you can collect the points. If it has some child $$$v$$$ with $$$t_v = 3$$$, you may go to some other child $$$w$$$, collect its points, come back to $$$u$$$ and then go to $$$v$$$. Alternatively, you may just go to some child and collect its points.

    Equivalently, we want to color the tree in three colors: white (did not collect points), black (did collect points) and red (did collect points but "in passing" like from $$$w$$$ above, without chance to collect points from its children). The coloring must satisfy the following constraints:

    • A red vertex may have only white children.
    • Any vertex must have at most one black and one red child.
    • A vertex can only have a red child if it also has a black child with $$$t_i = 3$$$

    and must maximize the sum of points in red and black vertices. This can now be solved using a classical tree dp, where $$$\mathrm{dp}[u][k]$$$ is the maximum number of points you can get from the subtree of $$$u$$$ given that $$$u$$$ has the color $$$k$$$.

    • »
      »
      »
      5 лет назад, скрыть # ^ |
      Rev. 2  
      Проголосовать: нравится 0 Проголосовать: не нравится

      Hi there, I followed your guide, but maybe there's some bug that I cannot find, can you help me? Thx

      Implement
  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +11 Проголосовать: не нравится

    D: This sorting algorithm can be reformulated as follows: construct an increasing subsequence greedily (start from the first element, each time take the next element strictly bigger then the current maximum), cycle shift it by one, then perform an insertion sort. And you need to print the length of the increasing subsequence + the number of swaps performed by an insertion sort. For one array this is easily done in $$$O(n\log n)$$$: find the increasing subsequence in $$$O(n)$$$, cycle shift it, then for each element add the number of distinct values on the prefix, that are bigger than this element.

    Now we need to recalculate the answer after adding an element to the array. If this element is not a maximal one, this is pretty easy, since it does not affect any of the previous steps. If this element is a new maximum, the length of the increasing subsequence increases by one, and also one more swap is needed for some iterations of the insertion sort. It is not hard to understand that this swap is needed for the elements that are positioned after the second occurrence of the previous maximum (hard to explain, but easy to understand from some examples). After that everything can be easily recalculated.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by chenjb (previous revision, new revision, compare).

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +24 Проголосовать: не нравится

How to solve B, F, G, K?

Also, are there any solutions for E without any matrix multiplications?

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +67 Проголосовать: не нравится

    E: I'm pretty sure all solutions would be pretty much equivalent to matrix multiplications. The key here is that the operations (a += k and history += a^2) are linear operations on history, a^2, a, and 1, which lets us compose them succinctly. Matrices and matrix multiplication are just notations for linear operators, but I think all solutions probably rely on this linearity.

    F: There are 2 cases, either one polygon contains the other, or there's a separating line through the origin. In the first case, the outer polygon must exactly be the convex hull of all points, so we can check this solution. In the second case, we can sort the points by the angle to the origin, and then sweep the angle of the dividing line. Note that within each convex polygon, the points must be sorted by angle to the origin, so we can precompute whether each triple of neighboring points is actually convex. This lets us efficiently check the validity of any solution, so we can just take the max of all valid ones.

    K: This problem asks for the number of sets of 4 points which form and independent set, minus the number of sets which form a clique. Let's focus on counting the number of independent sets. We can count this using PIE: we want the number of sets of 4 points, minus the number of sets of 4 points and 1 edge among them, plus the number of sets of 4 points and 2 edges among them, etc. In particular, we need to add the number of sets of 4 points with 6 edges among them, i.e. cliques. Thus, we only need to count the number of each configuration of 4 points with up to 5 edges. These are:

    1. Four points with zero edges
    2. Single edge and 2 points
    3. Two edges with a common vertex and a point
    4. Two parallel edges
    5. Three edges sharing a common vertex (a claw)
    6. Three edges forming a triangle and a point
    7. Three edges forming a path
    8. Four edges forming a triangle with an extra edge attached
    9. Four edges forming a square
    10. Five edges forming two triangles glued together

    Of these values, numbers 1 through 5 are trivial, numbers 6, 7, 8, and 10 can be counted by enumerating all triangles, and number 9 requires counting 4-cycles. We do both of these in $$$O(E \sqrt{E})$$$ time. There are a few ways to do this, here's a pretty nice one.

    Sort all vertices of the graph by degree, and then direct each edge from the earlier (smaller) vertex to the later one. Then, we claim that each vertex has outdegree at most $$$\sqrt{2E}$$$. This is because all later vertices must have degree at least equal to your outdegree, but the total degree is $$$2E$$$, so there can be at most $$$\sqrt{2E}$$$ out-neighbors.

    Now, to enumerate triangles, we can casework on the edge between two smallest vertices; fixing this, there are at most $$$\sqrt{2E}$$$ choices for the outedge from the middle to the largest vertex, so we can enumerate all triangles in $$$O(E \sqrt{E})$$$ time.

    To enumerate 4-cycles, we will casework on the diagonal containing the largest vertex; let's denote that vertex by $$$z$$$ and the opposite vertex by $$$x$$$. Fix $$$x$$$, and consider every $$$y$$$ adjacent to $$$x$$$; then, $$$z$$$ must be an out-neighbor of $$$y$$$. Thus, we can enumerate them naively and count the number of times each $$$z$$$ is 2 away from $$$x$$$; taking those counts choose 2 gives the number of squares. The total runtime is also $$$O(E \sqrt{E})$$$, since each (undirected) edge is used twice as the edge between $$$x$$$ and $$$y$$$, and $$$y$$$ has at most $$$O(\sqrt{E})$$$ out-neighbors.

    We had this code in our ICPC book from before: https://github.com/ecnerwala/icpc-book/blob/master/content/graph/cycle-counting.cpp.

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +19 Проголосовать: не нравится

    G: Instead of diameter, we can maximize the length of some path instead (and don't care about any other paths). We can use $$$dp[p][x][y]$$$, meaning the maximum path length from node $$$x$$$ to node $$$y$$$, and that we are about to place $$$a_p$$$.

    For each path $$$(x,y)$$$, we additionally need to store the number of "free" edges we can use without extending $$$(x,y)$$$.

    For a fast transition, we add two more states: $$$dx$$$ is a boolean meaning we have not assigned some cost to the edge $$$(x', x)$$$ ($$$x'$$$ is the previous $$$x$$$), and $$$dy$$$ the same thing but for $$$y$$$. Then the transition depends on $$$dx$$$ and $$$dy$$$: in particular, if $$$dx=1$$$ we can either use a current "free" edge or iterate on vertices adjacent to $$$x$$$ for extending the path. If $$$dx=0$$$ we can either use a "free" edge or assign $$$a_p$$$ to the last edge of $$$x$$$ (so increase the value of $$$dp$$$ by $$$a_p$$$). Same for $$$dy$$$.

    Total complexity is $$$O(n^3)$$$.

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +8 Проголосовать: не нравится

    Can you explain, what is matrix idea to solve E?

    • »
      »
      »
      5 лет назад, скрыть # ^ |
      Rev. 4  
      Проголосовать: нравится +19 Проголосовать: не нравится

      I'll skip the reduction to a single 1D segtree with "add on range" and "get a historic sum of squares on range".

      You can store a vector of $$$K$$$ values in each node of a segtree and represent your push (lazy update) operation as a $$$K \times K$$$ matrix that moves some of these values into others with different coefficients. Applying a lazy tag to a node is multiplying a vector by a matrix. Pushing a lazy tag into children is multiplying their matrices by yours.

      I believe, the sum of squares is a non-trivial part if you never encountered it. You want to transform $$$\sum \limits_{i=l}^{r} x_i^2$$$ into $$$\sum \limits_{i=l}^{r-1} (x_i + \mathit{push})^2$$$. Rewrite as $$$\sum \limits_{i=l}^{r-1}(x_i^2 + 2 \cdot x_i\cdot \mathit{push} + \mathit{push}^2)$$$ = $$$\sum \limits_{i=l}^{r-1} x_i^2 + 2 \cdot \mathit{push} \cdot \sum \limits_{i=l}^{r-1} x_i + (r - l) \cdot \mathit{push}^2$$$.

      Thus, this vector of values in a node responsible for the range $$$[l; r)$$$ can be $$$(\mathit{historic~sum~x^2}, \mathit{sum~x^2}, \mathit{sum~x}, r - l)$$$. So there are $$$4$$$ values and you need a $$$4 \times 4$$$ matrix to deal with them.

  • »
    »
    5 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится +28 Проголосовать: не нравится

    B: we will try to reduce both graphs to canonical form. If canonical forms coincide, we perform the reduction for $$$A$$$, and undo the reduction for $$$B$$$ after that.

    If you make operations $$$(a, b, c, d, x)$$$ and $$$(b, a, c, d, x)$$$, weight of $$$ab$$$ edge will increase by $$$2x$$$, and weight of $$$cd$$$ will decrease by $$$2x$$$. This allows to change weights pretty much arbitrarily, preserving the total sum, as well as parity of each individual weight. We will "canonize" parity first, and then do some even steps.

    If $$$n$$$ is small (say, at most $$$5$$$), we can look for the lex. smallest reachable parity configuration with BFS. If $$$n = 4$$$, sum of opposite edge weights is always preserved, thus after parity fixing we can make all edges not adjacent to vertex $$$1$$$ to be $$$0$$$ or $$$1$$$, and that's canonical form. If $$$n = 5$$$, we can make all edges other than $$$(1, 2)$$$ to be $$$0$$$ or $$$1$$$ by transferring their weights to $$$(1, 2)$$$ with the $$$2x$$$ gadget above, possibly with an intermediate step.

    If $$$n \geq 6$$$, we can always make at most one edge have odd weight. If edges $$$ab$$$ and $$$cd$$$ are odd, and $$$e, f$$$ are any other two vertices, then applying operations to $$$acef, adef, bcef, bdef, abcd$$$ (all with $$$x = 1$$$) makes $$$ab$$$ and $$$cd$$$ even while preserving all other parities. Doing this repeatedly (possibly with intermediate steps, like above) we can make all edges, except possibly $$$(1, 2)$$$, have even weights. After that we can gather all even weights into $$$(1, 2)$$$ similar to the above.

    UPD: also I'm stupid and we just need to reduce the difference of $$$A$$$ and $$$B$$$ to all zeros lol.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +26 Проголосовать: не нравится

Is it right that scanf/printf are really slow on CodeForces?

During the Open Cup round, I used scanf and printf in problem H, it passed in less than 500ms. But when I submit the solution to gym after the contest, it got TLE (time limit is 2 seconds, so it's at least 4 times slower than Yandex.Contest).

Then, I replaced scanf with cin and fread, and they both got accepted quickly and in almost the same time as on Yandex.Contest.

Appendix
»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

How to solve M?