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

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

D2A author: 300iq, cdkrot, developer: 300iq

Tutorial is loading...

D2B author: isaf27, developer: cdkrot

Tutorial is loading...

D1A author: isaf27, developer: isaf27

Tutorial is loading...

Jury's solution (isaf27): 40973089

D1B author: 300iq, developer: Flyrise

Tutorial is loading...

D1С author: pashka, developer: cdkrot

Tutorial is loading...

D1D author: tourist, developers: qoo2p5, VArtem

Tutorial is loading...

The first solution: 40971595 and the second solution: 40971634.

D1E author: isaf27, developer: isaf27

Tutorial is loading...

Jury's solution (by isaf27): 40973023

D1F author: GlebsHP, developers: demon1999, PavelKunyavskiy

Tutorial is loading...

Credits to all jury members, who contributed to this round and EJOI: tourist, PavelKunyavskiy, niyaznigmatul, 300iq, GlebsHP, pashka, qoo2p5, VArtem, demon1999, Flyrise, ifsmirnov, isaf27, yeputons, cdkrot.

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

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

Downvoted, thanks for explaining the "simple cases analysis" for Div1D

»
8 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится -12 Проголосовать: не нравится

During the round,I noticed that in div2 B it is written that "In one operation you can select some i (1 ≤ i ≤ n) and replace element ai with ai & x,",which it's said "some",meaning I can choose an many i(s) as I like.So I think the max ans should be 1 instead of 2(Maybe it's just a translation mistake).

However, I got tons of Wrong Answer because of this. So,is it a mistake....or because I am too weak in English?

SORRY FOR MY POOR ENGLISH

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

my div1 D solution

40970859

I coded so many lines...

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

some of the submissions in editorial can not be visited

»
8 лет назад, скрыть # |
← Rev. 12  
Проголосовать: нравится +42 Проголосовать: не нравится

In Div2E/Div1C, here is a simplier solution:

Let dp[i][j][k] means the min cost that we are at pos i, we have built j houses in [1,i]and k means if we are going to build a house at pos i ( k = 0 or 1 )

when transforming , it's clear that:

when k = 0, we can use dp[i][j][0] to update dp[i+1][j+1][1] and dp[i+1][j][0],means if we are going to build a house at pos (i+1)

when k = 1, we can use dp[i][j][1] to update dp[i+2][j+1][1] and dp[i+2][j][0],means if we are going wo build a house at pos (i+2) ( we cannot build at pos(i+1) now since pos i has already had a lovely house)

You can see the DP equation in my Code: 40965480

#define Mymax(a,b) if(a<b) a = b;
int P( int pos , int goal ){
	if( a[pos] <= goal ) return 0;
	return a[pos] - goal;
}
dp[1][0][0] = 0;
	dp[1][1][1] = 0;
	int div2 = (n>>1) + (n&1);
	For(i,n){
		Forx(j,0,div2){
			For0(k,2){
				#define N dp[i][j][k]
				if( dp[i][j][k] == -INF ) continue;
				if(!k){
					Mymin(dp[i+1][j+1][1],N+P(i,a[i+1]-1));
					Mymin(dp[i+1][j][0],N);
				}else{
					Mymin(dp[i+2][j+1][1],N+P(i+1,min(a[i],a[i+2])-1));
					Mymin(dp[i+1][j][0],N+P(i+1,a[i]-1));
				}
			}
		}
	}

Complexity: O(n2)

I used the algorithm during the contest and acceptted,and I think it's much clearer than the Editorial

SORRY FOR MY POOR ENGLISH

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

Editorial for Div. 2 B:

"Clearly, if it is possible then there are no more than 2 operations needed."

Can someone explain that? Thanks in advance.

»
8 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится +19 Проголосовать: не нравится

In tutorial of Div1F, I guess it should be d ≥ dp[A] instead of d ≤ dp[A]. Also O(2nn2) seems to be sth like O(2n n2) (wow it seems to be a bug of codeforces).

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

can someone explain more clearly for div2D ?

»
8 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится +1 Проголосовать: не нравится

Hey I noticed something strange on div2D/div1B:

When you submit the O(nlogn), its actually faster than O(n) dsu.

Strange right?

My O(nlogn) — 40990303 — 124 ms (path compression)

My O(n) — 40990296 — 155ms (path comp + ranking)

I thought, it must just be me. But I was curious, so I also edited vamaddur's solution to see if similar would happen.

The same pattern happened, even with different implementations (he had some debugging stuff, etc):

O(n) — 40963207 — 483 ms (path comp + ranking)

My edit on his O(n) to O(nlogn) — 40990415 — 311ms (removed ranking, only path comp)

Now of course I understand complexity is not everything, there is constant factor. But I don't understand how even bad constant factor of one O(n) solution can overcome logn factor of slower dsu.

I think this is strange, maybe it has something to do with the data? Why does the nlogn run faster than the linear solution?

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

    DSU is O(NlogN), due to the get father part going through at most logN different DSUs before arriving at rhe correct one

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

    I remember that path compression + ranking is not O(n)...

    Isn't it O(N * InverseAckermann(N))?

    BTW, maybe that what makes ranking slower is the if-else statements and more RAM access for array rank?

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

      My comment above.

      And yeah I suspect maybe something like that, but even if you get the max value from a(4e5) = 4

      and you compare O(4n) with O(nlogn)

      log2(4e5) = 18.6something

      so to get 4n > 18n the added constant factor from if-else statements + accesses would have to make it at least 4 or 5 times slower.

      Now I'm wondering if that is actually the case, or that data is unbalanced. If that is actually the case, why not always just write nlogn dsu with the better runtime?

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

        As I know, the penalty for branch predicting failure in CPU is huge. And it's hard for CPUs to predict complex conditional jump like the if-else statements in ranking...

        (Sorry for the poor English...Maybe the proper noun isn't correct)

        BTW, if we consider the InverseAckermann(n) as a constant because it's capped at 4, why can't I say that since the n is capped at 2e5, my algorithm is O(1)?

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

          OK, implementing it with just if statements is still 155 ms.

          As about treating a(n) as constant factor, it is typically done because it is easier to think about. So I just call it O(n).

          As for making something large a constant factor, it might be useful, I'm not sure.

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

            I think he means that the if statements are harder to get branch predicted

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

            Well, actually I mean that the if statements in ranking DSU if(rank[x]>rank[y]) is complex for CPU (it used two RAM references) and it's harder than other branches (like loops) to get branch predicted (value of that expression is almost random). So the conditional jump in ranking DSU (whatever it is, if or if-else) could be the performance bottleneck.

            Another thing that increases the constant factor could be cache miss in RAM accessing. Since the size of array rank is over 1MB so it couldn't be put into cache entirely, it can be another reason.

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

              So would using conditional operator remove this bottleneck?

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

                Maybe.

                Normally, the operator ?: is based on conditional value statements which run faster than conditional jump statements if the expressions have no side effect because there's no branch prediction here. So you can try the operator ?: to optimize that.

                Try this: prt[rank[x]>rank[y]?x:y]=rank[x]>rank[y]?y:x;

                But for RAM accessing...I have no idea with optimizing that.

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

Can someone explain more clearly div2B ?I don't understand why at most 2 operations will suffice for an equal pair??

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

    Firstly its obvious that you'll apply the operation to any element atmost once(because a&x == (a&x)&x ). Let's apply it to the value at position i. Suppose we couldn't find any element a[i]&x in the array. So we apply the operation to a position j. This makes the count of operations used = 2. Still we couldn't find any element a[j]&x in the array. Now suppose we find a position k, such that a[i]&x = a[k]&x. So, using the operation on the position j was a waste. So, at max 2 operations will always suffice. Rest of the elements need not be tampered with.

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

Which problems appeared in EJOI?

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

HELP with Problem B. I don't understand the editorial at all.

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

My solution for div1D, finally:

  • let's append undeletable 'a' and 'b' at the end of the original strings (trying both ways to do it) and group together consecutive identical letters
  • if both compressed strings have equal lengths, it has an easy greedy solution
  • the optimal solution will reach this situation in at most 2 steps
  • there are only a few types of operations we want to do in these two steps, it seems "move the first group from one string to the other" and "swap approx. half of one string with approx. half of the other string" are the only ones needed (6 types in total)
  • bruteforce these at most two steps, do greedy if possible afterwards, pick the best solution obtained this way

It has a large constant, but at least it should be provable more easily. It's still kind of a PITA to code.

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

Wow, Div1B has an amazing solution in my opinion. What a great problem! It is so easy to code, yet so hard to solve.

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

    help me with this problem ? if possible with a elaborate explanation . thanks !

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

      The solution is above, so I'll try to explain how to get there intuitively.

      First, consider an empty n by m grid. Observe that the minimum number of nodes is n+m+1 — you get that number by making an L shape. Why is it minimal? Well, you must at least have a element in every column and every row, and in a way, they have to support each other. That is, simply making a diagonal can control each column and row, but you won't really be able to get anything unless you have elements in the same column and row.

      But, if you do have 2 elements in the same row (say row 0), then they will support each other a lot! Suppose we have 2 elements in the same row, and suppose they're in columns 1 and 2. Then, if we put another element in column 1, we will control that row of column 2 automatically. So, if we can solve column 1, we can also solve column 2, and vice versa.

      So, in a way, row 0 links columns 1 and 2 together. Similarly, columns can link rows together. If we put an element in column 1, row 3, then solving row 0 will solve row 3 and vice versa.

      Thinking about this relationship, maybe you are inspired to draw these links as edges on a graph. Each element is a link, from row (whatever row it is) to column (whatever column it is). You end up with a bipartite graph. When two rows are in the same connected component, that means that for every solved element in the first row, there is a corresponding solved element in the second, and vice versa. If we can connect the entire graph, then we say that, if any element of a row is solved, the whole column is solved! And since we've connected the whole graph, we must have drawn connections to each column, so the whole graph must be solved!

      So, our goal is to make the described bipartite graph fully connected. To do this, count the number of connected components. Then, we want to add edges to connect them. We can always find an edge to connect 2 components here, so the answer is the number of disconnected components — 1. To count we do a very simple dfs.

      Here is my solution for implementation details. http://codeforces.me/contest/1012/submission/41098552

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

Another solution to Div1C (Div2E) is to extend the solution that you found for k and use it to find the solution for k+1.

Let's define used[i] = 1 if the i'th hill contains a flat, otherwise used[i] = 0.

To extend the solution from k to k+1, we need to build one extra flat, so we can make one of the following transformations to one of the contiguous subsequences:
1- Transform 0 0 0 → 0 1 0. That is, build a new house if it's neighbors are not occupied.

2- Transform 0 01010 0 → 0 10101 0. By this, we get an extra 1. Of course the length of this sequence is arbitrary.

Then you simply have to loop over the possible transformations and choose the transformation that minimizes the total cost.

However, keeping track of the total cost and the cost of transformations turned out to be a little bit tedious and that the DP solution is definitely much simpler to code. Anyway, here is my submission if someone is interested: 41124194.

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

I wrote a slow but correct dynamic programming for Div1D.And I found if the length of any string is large, decision making seems regular. You can found these regular patterns here.(in function g(x, y, d), where x represents the length of the first string, y represents the length of the second string, and d represents whether the first characters are different). Could anyone prove it or hack it?

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

Please help. What is complexity for this?

https://codeforces.me/contest/1012/submission/91080831

I thought it was n^3 but it got AC.