2

Codeforces Round #826 (Div. 3) Editorial

 1 year ago
source link: https://codeforces.com/blog/entry/107908?f0a28=1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
By Vladosiya, history, 6 weeks ago, translation, In English

6 weeks ago, # |

another opportunity to feel dumb

6 weeks ago, # |

G is good and can be extended to weighted graph

6 weeks ago, # |

Rev. 2  

+2

Nice contest and great editorial!

F a little harder

Nice G

6 weeks ago, # |

If we replace mar = *max_element(...) with *min_element(...) in problem D, we are getting AC in both cases. I did min element there so someone can just give example or any explanation why is it working? Thanks in advance :)

  • 6 weeks ago, # ^ |

    If the tree should pass the sanity check (i.e. Answer is not ), then any comparison between the left subtree and the right subtree should return the same result. You can observe this by trying to construct the input from the sorted order . You can see that there is no way to move elements from the left subtree to the right subtree (or vice versa), other than to swap the two subtrees entirely. Therefore, the comparison returns if the two subtrees didn't swap, and if they did swap.

    • 6 weeks ago, # ^ |

      Ohk, Thanks!

6 weeks ago, # |

Can someone explain F editorial? Thanks.

  • 4 weeks ago, # ^ |

    Imagine a segment with left and right points being and . Now, think about all different segments that have it's left points before (or exactly equals) . You will notice that all those segments (including ) are candidates to be the closest to the left point of aka . Or even intersecting with .

    When you realize that, the solution that comes in mind is: for every segment , search among all segments with left points smaller than or equals to with different color, the one with highest right point . After that, check if (some distance) or (intersecting segments).

    Of course this solution gives you a TLE. However, as we want to know all segments with left points smaller than or equals to our current right point , the idea is iterate over all segments in increasing order of right points. Also, keep a pointer to the segments with left points already considered (to find ). Update this pointer as you walk through values of .

    The remaining part of the solution is explained in the editorial. That is the part that was difficult for me to understand as well. Hope it heps.

6 weeks ago, # |

Video Editorial for Chinese:

Bilibili

  • 6 weeks ago, # ^ |

    Is there an english version of this?

    • 6 weeks ago, # ^ |

      you know,because my poor English

6 weeks ago, # |

Wanted to reach specialist using div3 as a ladder, instead got negative delta. bleh. Need to grind more.

6 weeks ago, # |

Problem D. To decide to swap or not we do not need to calculate maximum. Enough to compare the first element with middle value.

  • 6 weeks ago, # ^ |

    Yes, it's true, thanks

  • 6 weeks ago, # ^ |

    Rev. 2  

    0

    Modified merge sort (swap merge in this case) also works and runs in O(n*log(n))

6 weeks ago, # |

and could've been swapped, at least in my opinion is way easier than .

  • 6 weeks ago, # ^ |

    Rev. 2  

    +1

    hmm, idk, I found C to be easier, since constraints were small thus O(n^2) was possible.

6 weeks ago, # |

Rev. 12  

+1

I have another solution for C:

We calculate the sum of the whole sequence, and consider its divisors: For every divisor , we check whether we can divide the sequence into segments of sum , and calculate the length of the longest segment. Doing that for every divisor gives us the time complexity of , which is still good enough to get AC.

Solution: 175584583

  • 6 weeks ago, # ^ |

    Rev. 4  

    0

    Great, i've done the same idea, it can be divided (max segment )or not (all array)

    Solution : 175657862

  • 6 weeks ago, # ^ |

    Rev. 2  

    0

    Had the same solution during contest.

    Code: 175623834

  • 6 weeks ago, # ^ |

    Hey, can you help me understand how you came up with the time complexity for your solution? I was going for nearly the same solution but went up to n instead of sqrt(n) so got TLE :/

  • 6 weeks ago, # ^ |

    I also used the same logic.

    Code

  • 3 weeks ago, # ^ |

    Could you please explain, why this algorithm is ture?

  • 11 days ago, # ^ |

    Kubogi Can you please explain me why this approach is ture, I can't grasp

6 weeks ago, # |

What is wrong in my submission for problem D? 175630153

  • 6 weeks ago, # ^ |

    Take a look at Ticket 16316 from CF Stress for a counter example.

6 weeks ago, # |

I have a slightly different idea of C 1)I sum up all values of array 2)build a prefix sum of array 3)went through all divisor of Sum 4)now let Div be the current divisor then this div should exists In prefix sum,it multiple should exists, 5)I took the longest i In prefix sum where Div exist and updated the answer!!

My first solution got hacked just becoz I didn't consider 1 as divisor .

6 weeks ago, # |

There's another solution to B, which I believe to be more intuitive.

If n equals 3 print -1.

If n is even, then the permutation looks like this:

If n is odd, just print the permutation for n + 1, but without the first element, which will always be equal to n + 1, so the permutation is valid.

Solution: 175595206

  • 6 weeks ago, # ^ |

    In my opinion your solution seems a little bit more complicated than necessary and than the one given in the editorial.

    I did something similar, but instead of doing

    p = n, n-1, ..., n/2+1, 1, 2, n/2

    I just did

    p = n, n-1, 1, 2, ..., n-2

    That way it's easier to implement and this works for both even and odd values of n, so you don't need to handle those cases separately

    Solution: 175582981

    Anyways, it really doesn't matter much...

6 weeks ago, # |

Does anyone know what the 17th test case of test case 3 for F is? 175777495

  • 6 weeks ago, # ^ |

    This is not the 17th test case but here is a failing test case:

    Expected Output: 0 0 25 0 9 0

    Obtained Output: 0 0 25 0 43 0

    • 6 weeks ago, # ^ |

      Thanks

6 weeks ago, # |

I have another solution for G. It got AC but I'm not sure if it is actually correct.

Spoiler

6 weeks ago, # |

For problem D, we can first check all leaves. Start from a1, we consider every pair (ai,ai+1), it must be like (x,x+1) or (x+1,x), if not, we cannot sort it. Otherwise, when the form is (x+1,x) we are supposed to swap it. Put (x+1)/2 to its father node. After do this we get a new array which length is n/2. And repeat it until the array length is 1. link

6 weeks ago, # |

why isn't rating's updated yet?

6 weeks ago, # |

Rev. 2  

0

Wouldn't the complexity remain O(mn) for D even after pre-calculating min and max for each vertex since we are swapping elements at each level?

  • 6 weeks ago, # ^ |

    Rev. 2  

    -6

    We do not necessarily have to swap all elements of the left/right subtree. I used a bottom-up iterative approach for this. We enumerate as powers of two (including one) less than . And starting from , we try to fix the order of and . Now we can see that the indices we wil be comparing on the next step will be a subset of the current step. (Think of it as arithmetic progressions of ) This is due to the fact that if the subtrees below are sorted, then we can compare the leftmost element to see whether we need a swap or not. And as we will refer to a subset of the current step on the next step, just swapping the two elements suffices for counting the swaps. The sanity check is done by checking a certain invariant property which is true when the subtrees below are sorted and the tree is made from a perfect binary tree: . This solution is , you can check my submission (Python:175604510, C++:175815111) for further details.

  • 6 weeks ago, # ^ |

    D can also be done in O(n*log(n)) , variation of mergesort, here is the code

    Code Snippet

6 weeks ago, # |

Rev. 2  

0

Can anyone explain why 175793640 gives MLE on test 24 (problem G)? It works for other test cases which have higher n and m.

6 weeks ago, # |

I like E, pretty standard and good

6 weeks ago, # |

Rev. 5  

+3

Here's an alternative solution to F w/ time complexity and less code.

As done in the editorial, traverse the segments after sorting by left coordinate, and again after transforming to . Instead of keeping track of 2 maximal segments, though, we keep track of the rightmost endpoint of each color with a max segment tree, and when we are processing segment X, if the query result is to the right of X's left endpoint, we can set to 0, otherwise set to the distance between the left endpoint and the query result.

The above algorithm nearly works, except for when a segment is only adjacent to differently colored segments inside itself. Though, we can then use one additional check: the fact that if segment X contains the midpoint of segment Y, then segments X and Y intersect. This is also insufficient standalone as the converse is false, but kills the edge case. Using a std::multiset, we can perform it in .

Implementation: https://codeforces.com/contest/1741/submission/175824953

Alternative implementation, with an additional factor of in space and time complexity, but uses no data structures outside std::set<int>: https://codeforces.com/contest/1741/submission/175826713

(EDIT: the use of a segtree can be circumvented in my original solution with the bitwise maximum technique in this implementation, which should also improve execution time. Though, that is something one would be far less likely to come up with in contest.)

6 weeks ago, # |

Can someone help me understand the editorial for problem G? I'm not sure what the editorial is trying to say, and I'm finding it difficult to decipher the code in the given solution.

  • 6 weeks ago, # ^ |

    1. For each vertex, find all possible sets of friends with no cars to which it can give a ride via bfs.
    2. For each set of friends with no cars, determine if it is possible to give rides to them via dp.
    • 6 weeks ago, # ^ |

      Can u pls elaborate your second point. Thank you .

      • 6 weeks ago, # ^ |

        We make a dp on friends with cars as follows: if a set A of friends with no cars could be given rides and a new friend with a car can give ride to a set B, then A union B can be given rides.

        • 6 weeks ago, # ^ |

          ok thanks got something will figure out the rest myself.Thank you for the explanation.

6 weeks ago, # |

Another solution. May be intuitive using range trees.

175830429

But it uses extra space.

6 weeks ago, # |

I would like to share my DFS solution approach for problem E. There can be at most O(2*n) valid subarrays. Each segment is consisted of 2 parts length and numbers. In a segment the length can be either on left or on right. Now, if we consider a[i] as one segment's length indicating cell, then the segment will be either of [i-a[i],i] range or of [i,i+a[i]] range. Let's consider each index as a node. If there are two nodes(segments) having range [i,R1] and [j, R2] where R1+1==j, then we will put an edge between them. Now, lets run a dfs from node 1. If we can reach the node (n+1), then answer is "YES", otherwise "NO". (n+1) is just a dummy node at additional index (n+1). My submission: https://codeforces.com/contest/1741/submission/175659624

  • 6 weeks ago, # ^ |

    Did the same. I do think the DP solution is practically equivalent to the DFS solution though. If we model the DP solution as a DAG, we should get the DFS solution, therefore the two solutions are equivalent.

  • 6 weeks ago, # ^ |

    You have used directed graph. I tried to do it using undirected graph and I was getting WA (my submission). Can you explain the difference??

    • 6 weeks ago, # ^ |

      is a counterexample to the undirected graph approach.

  • 5 hours ago, # ^ |

    why running DFS from only FIRST node giving the correct solution? I thought the same approach but running DFS running for each node as source.

6 weeks ago, # |

Rev. 2  

0

Problem C can also be solved by considering all factors of the sum (sum of all elements of array), and trying to split the array for each factor. There can be maximum of log2(sum) factors making the complexity O(NlogN).

Here is my solution: https://codeforces.com/contest/1741/submission/175841633

  • 6 weeks ago, # ^ |

    Rev. 2  

    0

    Actually the number of divisors of is not bound to be lower than . We can use a number which is a product of many different primes for an example of this. Your statement is true for prime factors, but it is nowhere close to the truth for all factors. is a known upper bound for the divisor function for , though. ( is not a precise upper bound either, it is just an estimate)

    • 6 weeks ago, # ^ |

      Yes, it was my bad. The numbers of factors do not have a log2N upper bound.

      Also if the sum of elements are low, my solution can be faster than O(N^2) solution.

6 weeks ago, # |

Can someone explain the solution for C in more detail?

I tried drawing a stack diagram and all.

I even ran their code locally and it did not output the right answer.

6 weeks ago, # |

Does anyone know subcase 26 in test case 3 for G? 176090403

  • 6 weeks ago, # ^ |

    Take a look at Ticket 16317 from CF Stress for a counter example.

6 weeks ago, # |

176213193 which is my way to solve D using sparse table :)

6 weeks ago, # |

Rev. 2  

0

My D solution, iterative and using swap_range stl function

Spoiler

4 weeks ago, # |

haha bullshit

3 weeks ago, # |

Can someone explain the Problem F editorial? It is not easy to understand the concept/idea used in that.

3 weeks ago, # |

Rev. 2  

0

Hey, I came up with a different iterative solution. Wanted to drop it in if it is of use to someone.

The intuition is to check for sizes of multiple of 2.

First check consecutive blocks of size 1 and if there is disorder swap the blocks.

then check two different blocks of size 2 and if there is disorder swap the blocks.

Also I have created a validate function which can check if it is possible to form an increasing sequence.

Take a two blocks [5, 7] [8, 9] here min element in block 1 is 5. iterate over first block and check if absolute difference is less than block size. Here abs(7 — 5) will be 2. So we won't be able to arrange the whole tree in increasing order. Trying this with some of examples above and block of even larger size might clear things out.

As this is my first comment. Any suggestions on etiquette and improvements are welcome.

// Aabhas Sao, 19-11-2000
#include <bits/stdc++.h>
using namespace std;

#define ll long long int

bool validate(int segmentSize, int i, vector<int>& v) {
  int half = segmentSize / 2;

  int mn = v[i];

  for (int j = 0; j < half; j++) {
    if (abs(v[j + i] - mn) >= half) {
      // cout << v[j] << " " << mn << " " << half << endl;
      return false;
    }
  }

  mn = v[i + half];

  for (int j = 0; j < half; j++) {
    if (abs(v[i + j + half] - mn) >= half) {
      return false;
    }
  }

  return true;
}

void solve() {
  int n;
  cin >> n;
  vector<int> v(n);

  for (int i = 0; i < n; i++) {
    cin >> v[i];
    if (v[i] > n) {
      cout << -1 << endl;
      return;
    }
  }

  int skips = 2;
  int ans = 0;

  while (skips <= n) {
    for (int i = 0; i < n; i += skips) {
      int mid = i + skips / 2;

      if (!validate(skips, i, v)) {
        // cout << i << " " << skips << endl;
        cout << -1 << endl;
        return;
      }

      if (v[mid] < v[i]) {
        for (int j = 0; j < skips / 2; j++) {
          swap(v[i + j], v[mid + j]);
        }

        ans++;
      }
    }

    // cout << ans << endl;

    skips *= 2;
  }

  cout << ans << endl;
}

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int t;
  cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK