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

Автор AlphaMale06, 3 года назад, По-английски

Thank you for participating in the first ever Serbian Div. 3 Codeforces round!

Sorry

Also a massive thanks to Vladosiya for giving us a chance to create a divison 3 round!

1878A - How Much Does Daytona Cost?

Problem was authored and prepared by
Hints
Tutorial
Solution

1878B - Aleksa and Stack

Problem was authored and prepared by
Hints
Tutorial
Solution

1878C - Vasilije in Cacak

Problem was authored and prepared by
Hints
Tutorial
Solution

1878D - Reverse Madness

Problem was authored and prepared by
Hints
Tutorial
Solution

1878E - Iva & Pav

Problem was authored and prepared by
Hints
Tutorial
Solution

1878F - Vasilije Loves Number Theory

Problem was authored and prepared by
Hints
Tutorial
Solution

1878G - wxhtzdy ORO Tree

Problem was authored and prepared by
Hints
Tutorial
Solution
Разбор задач Codeforces Round 900 (Div. 3)
  • Проголосовать: нравится
  • +131
  • Проголосовать: не нравится

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

Pretty balanced contenst

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

reverse madness was a cool one

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

Thanks for the fast Editorial.

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

Very interesting problem set, especially problem F

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

One of the best Div3. D problem, first I just printed valued of a,b (cause nothing else was coming in my mind :)), and then i was not difficult to see that for each possible a there is unique b

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

The idea behind E is nice but you can just code a sparse table to handle the query part from the binary search.

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

Can you please help me see why the code below times out? This code is for E. Thank you very much!

#include<bits/stdc++.h>
using namespace std;
int a[200010];
int sl,k;
int check(int x)
{
	int res = a[sl];
	for(int i=sl+1;i<=x;i++)
	{
		res &= a[i];
		if(res<k) return 0;
	}
	return 1;
 
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int q;
		scanf("%d",&q);
		while(q--)//Խ��ԽС
		{
			scanf("%d%d",&sl,&k);
			if(a[sl]<k) printf("-1 ");
			else{
			int l=sl,r=n;
			while(l<r)
			{
				int mid=(l+r+1)/2;
				if(check(mid)) l=mid;
				else r=mid-1;
			}
			printf("%d ",l);
			}
		}
		printf("\n");
	}
}
»
3 года назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

I have a slightly different implementation for Problem G . My approach is the same as the editorial (finding the selective nodes where the bitwise or changes).

However to find these nodes, instead of using binary search, we can maintain a map for every node. The map will have the $$$ closest $$$ $$$ ancestor $$$ to the current node for each distinct bitwise or possible. To find such ancestors we can use a map and iterate on it.

Implementation

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

I'd like to rephrase the proof of Problem C.

The key observation is that we can always change the sum of k numbers from s to s + 1, given that s is not the maximal. The proof comes as follows. Assume that we have a set of k numbers which sum to s. Let denote the maximal among the k numbers as m. If m < n, we can always achieve s + 1 by replacing m with m + 1 and the proof is done. If the maximal is n, we can prove it by contradiction as shown in the tutorial, i.e., n, n — 1, ..., n — k + 1 will belong to the set. This set will yield the maximal and contradicts the assumption that s is not the maximal.

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

    If m < n, we can always achieve s + 1 by replacing m with m + 1 and the proof is done.

    m < n, so maximal is not n it is mentioned. even if it is n, we have to replace next maximal by +1 if it does not already exist. so on...

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

In problem G, I don't understand why for each bit, we choose the vertex z such that it contains that bit, and z is closest to x (or y). What happen if we choose z such that it is not the closest?

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

    Because it would produce the same results with the closest one. Therefore we don't have to check that node

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

      I don't know if I misunderstand something. I think that if we choose another vertex that is not the closest one, the result for the current bit which we want will stay the same, but we don't know whether bits in other positions will increase the answer or not.

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

        That's why we need to consider both nodes

        For example assume the path from $$$u$$$ to $$$v$$$ looks like this :

        $$$000, 001, 100, 101, 000, 010$$$

        Here are the path looks for each bits from $$$u$$$ to $$$v$$$ :

        • bit $$$0$$$ : $$$0, 1, 1, 1, 1, 1$$$
        • bit $$$1$$$ : $$$0, 0, 0, 0, 0, 1$$$
        • bit $$$2$$$ : $$$0, 0, 1, 1, 1, 1$$$

        And for bits from $$$v$$$ to $$$u$$$ :

        • bit $$$0$$$ : $$$1, 1, 1, 1, 0, 0$$$
        • bit $$$1$$$ : $$$1, 1, 1, 1, 1, 1$$$
        • bit $$$2$$$ : $$$1, 1, 1, 1, 0, 0$$$

        For the sake of explanation, let's number the nodes in the path with $$$1, 2, 3, 4, 5, 6$$$ (where $$$u=1$$$ and $$$v=6$$$)

        Now the closest nodes with $$$u$$$ that has a bit on for each bits are : $$$2, 6, 3$$$

        And the closest nodes with $$$v$$$ are : $$$4, 6, 4$$$

        Notice that the only important nodes are $$$2, 3, 4, 6$$$

        Node $$$5$$$ — for instance — is not important because from the perspective of $$$u$$$, the bit $$$0$$$ and $$$2$$$ will be "turned on" at node $$$2$$$ and $$$3$$$ respectively. While the bit $$$1$$$ is still "turned off" at node $$$5$$$

        The key observation here is once the bit has turned on within a path, it will never be turned off again because the nature of the $$$\text{OR}$$$ operations

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

For problem E, we can calculate every position, the first 0 to the right of every bit.

Then for each query, iterate each bit from low to high, and check first 0 to the right. If the current bit of k is 1, it needs to satisfy all the smallest right end points that are not 0. If the current bit of k is 0, since we iterate from low to high, the rightmost non-0 can be greater than or equal to k.

I am not sure if my solution is correct, after all, it has not passed the system test. But I want to share my ideas with you, and the code is as follows:

https://mirror.codeforces.com/contest/1878/submission/225352692

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

If someone prefers video explanations or interested in knowing how to think in a live contest or reach to a particular solution.
Here is my live screencast of solving problems [A -> E] (with detailed commentary in Hindi language).

PS: Don't judge me by my current rating :(

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

Hello. I have a question about Problem G. Why is the complexity not q*logA*logn*logn? Because finding the intersection points takes logA time, finding LCA takes logn time, and finally calculating by bits also takes logn time. I'm a little confused here,and my code get TLE.

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

E had a very long implementation, a little bit much for div3 question imo.

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

don't say sorry contest was very nice. All the problems were very interesting.

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

there's a very simple O(N+Q) solution for E 225432409

First, notice that the only positions of R that change a[L]&...&a[R] are those where the bit which was set in a[L] gets reset. Calculate the next positions where each bit gets reset and store them. Then for each query iterate over those "important" R positions and update the current value of a[L]&...&a[R]. If at a certain R the answer stops being greater than K, then the answer is R-1, otherwise the answer is N-1.

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

Can I solve the problem E using segment tree? For each query I can use binary search to find the value of "r" and find the value of f(l,r) using query method of segment tree. Time complexity O(q*logn*logn). But I am getting wrong answer after performing binary search.

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

I think the most easier way (I mean no need handle bit by bit) to do 1878E - Iva & Pav is to use seg tree. Here is my solution: 225454109

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

In D, I used binary search to get the indices, then calculated all the reversals I have to do, then just copy paste a solution of CSES substring reversals. Even if the CSES solution uses treaps, you still can just copy a solution without thinking about the treaps part

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

I've observed this thing regarding all ICPC-style contests on CF(i.e., div3/div4/edu rounds): fast solving doesn't matter as much as it matters in normal rounds.

For eg. contestants who solved the same no. of problems as me in this div3 but half an hour before me are ranked just 400 places ahead of me.

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

In problem C it should be the sum of 1 to n-k elements (4th line)

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

Awesome round in general. The problem are balanced and cover a lot of topic. I really like problem F.

However C is a little bit adhoc but I think it is fine.

And in my opinion, the gap between C and D is close enough.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
sparse tables are a little bit too advanced of a topic for div3 E

Meanwhile problem G: range minimum query, binary lifting, LCA.

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

This is a snippet of neal's solution of D

snippet

Not getting why max(x, l[i] + r[i] - x) is not being considered while doing the swap or even during the preprocessing of queries.

Edit: Ok, got it. So the answer lies in this statement — It is easy to see that the modifications x and n - x + 1 are equivalent.

Can this CSES task be also solved by similar trick, or advanced DS like treap is mandatory?

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

Can Someone explain why my code gave TLE ? 225358802

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

F is a very nice problem. Thanks for this round. Hope we see you again.

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

During testing, I found a nice offline solution for E.

The idea is to iterate from right to left and keep the value for each current prefix. When the values $$$f(i,i)$$$, $$$f(i,i+1)$$$, $$$f(i,i+2)$$$, ... are stored in some array, we can find the answer to some query by performing a binary search. In fact, we keep the right endpoints (denoted by $$$j$$$) in an array. We update the left endpoints ($$$i$$$) dynamically.

This is $$$O(n)$$$ memory. Updating the values when traversing from $$$i$$$ to $$$i-1$$$ can require up to $$$O(n)$$$ time. It seems like the total complexity is $$$O(n^2)$$$, which is untrue. In fact, it is amortized. Notice how we only need to update the values for which $$$f(i,j)$$$ changes. Modifying them decreases the total number of bits (among all values of $$$f$$$). The number of bits is $$$O(n \ log \ A)$$$, making the complexity $$$O(q \ log \ n + n \ log \ A )$$$.

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

Thank you for the round. Hope we see you again.

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

Man, there's an even simpler solution for B:

for(int i = 0; i < n; i++)
{
    std::cout << i + 5 << ' ';
}
»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I solved problem E by using a segment tree to query each segment in logarithmic time but it TLE'd in python3 during the contest. I found out just now that using Pypy is much faster and the solution is easily accepted. Is pypy a reasonable choice for competitive programming or will I still commonly run into this runtime trouble in the future?

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

Hall of fame level task names and descriptions

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

In problem D, instead of editorial's approach where it is taking into consideration the parity of number of operations as a condition to swap. I'm maintaining an array (1 based) which stores the number of operations on x [x = min(x, ri + li — x)]. For every query, I perform prefix[x]++ and take prefix sum of this array after all the queries. Now, if parity of number of operations (in the prefix sum array) before starting a new pair of (l, r) and number of operations at any index (in the prefix sum array) during the iteration in this pair is different, that would suggest a swap is required at that index. Otherwise, continue iterating. But I'm getting wrong answer as verdict. Please help me find where I'm going wrong.

Here is the submission link : https://mirror.codeforces.com/contest/1878/submission/225566736

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

    You do realize that $$$a=min(x,ri+li−x)$$$ in problem's text is a gimmick because it can be simplified to $$$a=x$$$ always?

    This means that in your query loop you can directly use $$$prefix[x]++$$$ without calculating $$$a$$$ and $$$b$$$ bounds at all.

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

Tutorial of D is terribly explained. Worst.

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

AlphaMale06 may you explain how sparse table can help here ? as in what we need to implement in the sparse table related to this problem ? sparse tables as far as i know is used to find minimum in a subarray how here it works ?

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

I personally feel D was easier than E. Maybe it were the long statements.

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

    Yeah it is, but many people learn some topics that are really advanced for their rank(like segment tree, not including pref sums here because it's easy to learn that idea even for newbie) and that's why E has more solves than D.

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

    I'm pretty sure they use sparse tables (the thing mentioned in the end of editorial for E), that's how they get a solution in $$$O(n \log(n))$$$

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

      My solution (linked above) used a segment tree and it is $$$O(n \log^2 n)$$$ (that's why memory is so small). I don't know why it runs so fast.

      Looking at the codes, neither of the other two linked solutions seem to use sparse tables. To me, it looks like they're using the fact that for fixed $$$l$$$, there are only at most $$$1 + \log_2 a = 31$$$ different values of bitwise and of subarray $$$[l, r]$$$ over all $$$r$$$. The "changing points" of the bitwise and can be calculated for each $$$l$$$ and stored in $$$O(n \log a)$$$ time and memory, and each query can be solved in $$$O(\log a)$$$ leading to a $$$O((n + q)\log a)$$$ solution.

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

In problem E, how can we use sparse table to get $$$f(l,r)$$$ in $$$O(1)$$$? I thought it's still needed to reconstruct the segment in $$$O(log_2(r-l))$$$ time? (I don't know much about sparse tables)

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

    If a query result can contain overlapping segments (min, max, or, and) then the sparse table only needs to look at two values for the answer. You find the largest power of 2 less than the range and calculate an overlap (eg for length 7 you do 2 queries of length 4 and include the value at position 4 twice).

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

I'm getting TLEd on G. What I am doing is, while binary searching the answer, I am fetching the ancestor. So basically the binary search is from 1 to the number of nodes in the path, and accordingly I'm fetching the count of bits. The implementation isn't the best, but it works. This is heavy on time because during my binary search I'm constantly binary lifting to find the node, so the binary search costs O( log(n) * log(max(a)) ). Combine that with query and it TLEs out. I cannot clearly understand how the editorial does it in O( log(n) + log(max(a) ). Any help will be appreciated, thanks in advance!

https://mirror.codeforces.com/contest/1878/submission/225749618

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

    I couldn't get how to do binary search in $$$O( \log{(n)} + \log{(max(a)} )$$$ too. Also there is no binary search in G's solution that is attached to the editorial, so I couldn't understand it from the code either. But I somehow managed to get an AC with a solution similar to yours. I'm doing binary search on the path from LCA to x to find highest and lowest occurrence of each bit (and from LCA to y). On each iteration of binary search I use binary lifting, so my binary search costs $$$O(\log{^2(n)})$$$ and I'm doing it for each bit, so I have $$$O(\log{(max(a))} \cdot \log{^2(n)})$$$ per query and $$$O(q \cdot \log{(max(a))} \cdot \log{^2(n)})$$$ is my overall asymptotic. With some non-asymptotic optimizations it gets AC:

    https://mirror.codeforces.com/contest/1878/submission/241103000

    Sorry for necroposting :D

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

For E, solution has mentioned that we can use sparse table also.I am learning segment tree currently..

I think segment tree can also be used here, am i correct?

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

Good contest and wonderful tutorial! Thanks.

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

Extended proof for F which may be useful in the future: If $$$x$$$ and $$$y$$$ are coprime, then $$$d(x\cdot y) = d(x)\cdot d(y)$$$

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

Problem C: Note that the sum of n over all test cases may exceed 2⋅105.

TC 05: 10000 194598 194598 10085825445 196910 196910 19386872505 193137 193137 6236620375 194427 194427 8160790120 ...

shouldn't O(n) also be accepted according to constraints? have i missed something?

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

Can any of you tell me how the E question was optimized with a hash table, the official question solution doesn't give any specific instructions.

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

For problem F solution 2, I was actually originally going to do this solution for the problem, but I was deterred because to find prime divisors and their exponents for $$$d(N)$$$, I have to find prime factorization of $$$d(N)$$$. Thus, we need to keep track of the smallest prime factor of numbers up to 1e9 (because $$$d(N)$$$ is bounded by 1e9) if we want logarithmic complexity. This uses too much memory. Has anyone figured out an implementation to find this prime factorization without use of smallest prime factor?

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

Hye guys!

You can see the detailed solutions for the problems A,B and C with proofs from my youtube video below:

https://youtu.be/odTQC7AOL3s?feature=shared

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

my segment tree solution for E 227542958

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

Is problem G possible in O(n log n)? The part where you calculate the ORs for each node can be optimized by noticing that the total value of the sums of the g function will increase by 1 in the first occurence of the bit and decrease by 1 in the last occurence of the bit (going from x to y). With that in mind we can just go from the closest important node to X to the last important node and keep track of the current sum.

However the bottleneck is still there in finding the important nodes. Is there a way to optimise it O(nlogn)?

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

why does this code fail 255033091 and when i change the line m=m1 to add_divs(n,m) it gets acc why if i change m=m1 it fails

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

I wrote a code for question E where I would be storing the suffix of the set bits occurring and using them to see what might be the last position of R where we might get a higher value and also checking the case where the value of our bits are same as K and we checked how many set bits are making the R larger. here is the code but it is failing. can anyone explain please.

My Code