FelixArg's blog

By FelixArg, history, 3 months ago, translation, In English

Thank you for participating! I hope you enjoyed the problems.

2233A - AI Project Development

Idea: FelixArg

Tutorial
Solution (FelixArg)
Rate the problem

2233B - Different Distances

Idea: FelixArg

Tutorial
Solution 1 (FelixArg)
Solution 2 (FelixArg)
Rate the problem

2233C - Cost of a Bracket Sequence

Idea: BledDest

Tutorial
Solution 1 (FelixArg)
Solution 2 (FelixArg)
Rate the problem

2233D - Goods on the Shelf

Idea: FelixArg

Tutorial
Solution (FelixArg)
Rate the problem

2233E1 - Permutation Transmission (Easy Version)

2233E2 - Permutation Transmission (Difficult Version)

Idea: FelixArg

Tutorial
Solution E1 (FairyWinx)
Solution E2 (FelixArg)
Rate the problem

2233F - Shortest GCD Paths

Idea: FelixArg

Tutorial
Solution (FelixArg)
Rate the problem
  • Vote: I like it
  • +28
  • Vote: I do not like it

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

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

»
3 months ago, hide # |
Rev. 3  
Vote: I like it +2 Vote: I do not like it
This also works for B.
  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it +15 Vote: I do not like it

    Here's my construction, which doesn't require separate handling for odd and even $$$n$$$:

    Spoiler
    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Yea, yours looks much better. Thank you so much!

      • »
        »
        »
        »
        3 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        mine is a little complicated... ~~~~~~

        include<bits/stdc++.h>

        define ll long long

        using namespace std;

        int main(){ int t;cin>>t; while(t--){ int n;cin>>n;

        vector<int> A;
            if(n==2){
                cout << "1 2 1 2 2 1 1 2\n";
                continue;
            }
           for(int i=1;i<=n;++i){
            A.push_back(i);
            A.push_back(i);
           }
        
        
           if(n&1){
            for (int i = 1; i < n; i += 2) {
        
            A.push_back(i);
            A.push_back(i+1);
            A.push_back(i);
            A.push_back(i+1);
        }
        A.push_back(n);
        A.push_back(n);
        swap(A[A.size()-2],A[A.size()-3]);
           }
           else{
            for(int i=1;i<=n;i+=2){
                A.push_back(i);
                A.push_back(i+1);
                A.push_back(i);
                A.push_back(i+1);
           }
           }
        
           for(auto &i:A)cout << i << ' ';
           cout << '\n';
           cout << '\n';
        
        }

        } ~~~~~~

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Beautiful construction.

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      waw frr u ve done a brilliant job with this :)

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Well Here is mine, without any cases either, though this is a terrible solution but yet kinda unique am I right or am I right? 377940813

      for those who dont want to open a new link
    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      heck this solution is so cool! T_T

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      here is mine

      void sol() {
          int n;
          cin >> n;
       
          vector<int> a(4 * n);
          for (int i = 0; i < n; i++) a[i] = i + 1;
          for (int i = n; i < 2 * n; i++) a[i] = i % n + 1;
          for (int i = 2 * n; i < 3 * n; i++) a[i] = n - i % n;
          for (int i = 3 * n; i < 4 * n; i++) a[i] = i % n + 1;
          
          if (n % 2 == 1) {
              swap(a[3 * n - 1], a[5 * n / 2]);
          }
       
          for (int i = 0; i < 4 * n; i++) {
              cout << a[i] << " \n"[i == 4 * n - 1];
          }
      }
      
    • »
      »
      »
      2 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      mine also doesn't require case work

      Spoiler
  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it
    My Idea
  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    You can also random shuffle. 377929631

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Hmm, I'm not very familiar with this kind of solution. Thank you so much :)

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    This also works:

    a = [1,2,...,n,1,1,2,2,...,n,n,1,2,...,n] if(n%2){ swap(a[0], a[n/2]) } print(a)

    • »
      »
      »
      3 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Nice one. Seems like there are a lot of possible solutions for this problem. Thank you!

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it
    for _ in range(int(input())):
        n = int(input())
    
        """
        n = 2
        2 1 1 2 1 2 2 1 
    
        n = 3
        3 2 1 1 3 2 1 3 2 3 2 1
        
        n = 4
        4 3 2 1 1 4 3 2 1 4 3 2 4 3 2 1
        
        n = 5
        [5 4 3 2] 1 1 [5 4 3 2] 1 [5 4 3 2] [5 4 3 2] 1
        """
    
        block = list(range(n, 1, -1))
        ans = block + [1, 1] + block + [1] + block + block + [1]
        print(*ans)
    
»
3 months ago, hide # |
 
Vote: I like it +16 Vote: I do not like it

Handled cheaters very well :>

»
3 months ago, hide # |
Rev. 4  
Vote: I like it +8 Vote: I do not like it

377959479

did anyone do B like this?

for(int i = 1; i <= n; ++i) {
        cout << i << " ";
    }
    for(int i = 1; i <= n; ++i) {
        cout << i << " " << i << " ";
    }
    for(int i = n - 1; i >= 1; --i) {
        cout << i << " ";
    }
    cout << n;
»
3 months ago, hide # |
 
Vote: I like it +20 Vote: I do not like it

Holy smokes E is beautiful but also I have no idea how I could have seen that myself :(

»
3 months ago, hide # |
 
Vote: I like it +8 Vote: I do not like it

Its me or C was too hard??

»
3 months ago, hide # |
 
Vote: I like it -7 Vote: I do not like it

Is this right for F? It took me about an hour on D and I couldn't submit my code of F in time at last because the page got stuck while loading :(

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node{int f,e;inline bool operator<(const Node &other) const{return e>other.e;}};
int n,a,b,l,c,u[19],v[19],z[150009],d[150009];
ll p;
vector<Node> g[150009];
map<int,int> m;
unordered_map<int,int> M;
priority_queue<Node> q;
bool vst[150009];
inline void f(int x){for(int i=2;i*i<=x;++i) if(!(x%i)){int o=0;while(!(x%i)) x/=i,++o;m[i]=max(m[i],o);}if(x>1) m[x]=max(m[x],1);}
void dfs(int i,ll x){
	if(i==l){++c,z[c]=x;return;}
	for(int j=0;j<=v[i];++j){dfs(i+1,x);x*=u[i];if(x>n) break;}
}
void dfs2(int i,int o,ll x,int r){
	if(r==l){if(x!=o) g[i].push_back((Node){M[x],max((int)x,z[i])/o}),g[M[x]].push_back((Node){i,max((int)x,z[i])/o});return;}
	while(1){dfs2(i,o,x,r+1);x*=u[r];if(x>n||p%x) break;}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>a>>b,f(a),f(b),p=a*b;
	for(auto x:m) u[l]=x.first,v[l]=x.second,++l;
	dfs(0,1);
	for(int i=1;i<=c;++i) M[z[i]]=i;
	a=M[a],b=M[b];
	for(int i=1;i<=c;++i){
		for(int j=0;j<l;++j) if(z[i]%u[j]==0){
			int o=z[i]/u[j],O=M[o];
			g[i].push_back((Node){O,u[j]}),g[O].push_back((Node){i,u[j]});
			dfs2(i,o,o,0);
		}
	}
	memset(d,0x3f,sizeof(d)),q.push((Node){a,0});
	while(!q.empty()){
		Node f=q.top();
		q.pop();
		if(vst[f.f]) continue;
		vst[f.f]=1,d[f.f]=f.e;
		for(Node &x:g[f.f]) if(!vst[x.f]) q.push((Node){x.f,x.e+f.e});
	}
	cout<<d[b];
	return 0;
}//a,b,c,d>=2 => max(ab,cd)>=max(a,c)+max(b,d),否则不妨 ab>=cd,a>=c,则 b<=d,于是 ab<a+d => d>a(b-1) => cd>=2d>a*2(b-1)>=ab 矛盾
»
3 months ago, hide # |
 
Vote: I like it +1 Vote: I do not like it

I don't know if I'm right, but another construction that works for B is: a b a b b a a b

Where distances from a, are:

2, 3, 1

And from b:

2, 1, 3

And maybe you have more settings if you figure out to swap the orders by keeping the "coherence" between the two interlinked distances. I'm not sure about that, though.

»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

got this solution for B by mistake

    ll n;
    cin >> n;
    vector<ll> ans;
    for(ll i=1;i<=n;i++){
        ans.push_back(i);
    }
    for(ll i=1;i<=n;i++){
        ans.push_back(i);
    }
    for(ll i=2;i<=n;i++){
        ans.push_back(i);
    }
    ans.push_back(1);
    for(ll i=1;i<=n;i++){
        ans.push_back(i);
    }
    for(auto i: ans){
      cout<<i<<" ";
    }
    cout << endl;
»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

;)

»
3 months ago, hide # |
Rev. 5  
Vote: I like it +9 Vote: I do not like it

I have a question for the editorial of F.

Spoiler
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

My solution for B was

If n is even then: 1, 1, 2, 2, 3, 3, ..., n-1, n -1, n, n, 1, 2, 1, 2, 3, 4, 3, 4, ..., n-1, n, n-1, n

Else if n is odd then: n, 1, 1, 2, 2, 3, 3, ..., n-1, n-1, n, n, 1, 2, 1, 2, 3, 4, 3, 4, ..., n-2, n-1, n-2, n-1, n

But this dont work for n = 2 so i checked if n == 2 then output 1, 2, 1, 1, 2, 2, 1, 2

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

What I did for B was simple :

n, 1, 1, 2, 2 ... n-1, n-1, n, n, 1, 2, 3, ...n-1, n, 1, 2, 3, ... n-1

Worked like a charm!

PS: Dont hack me :(

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I was only able to solve A and B

can someone explain me how to actually think for C problem

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    What is did was, assign a score for every bracket , for opening — count number of closing brackets after it. And for closing — count number of opening bracket before it. Just remove the one with with the highest count. Repeat the steps k time.

»
3 months ago, hide # |
 
Vote: I like it +13 Vote: I do not like it

I hate horrible implement of D.

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    I don't think it was horrible.

    My way of doing it was:

    • Push all indices of x into a set. For example the number "4" appears at indices [2, 3, 4, 5, 7].
    • Find the first x that is invalid (aka set.max — set.min + 1 > set.size)
    • Then you definitely have to fix x, and you must either swap the max or the min. From there it's a bit of manual casework but not too implementation slop in my opinion (the possibilities are min->slide it over to right before the second min, min->fill a hole in the middle, min->put it right after max, and same thing the other way)
»
3 months ago, hide # |
 
Vote: I like it +2 Vote: I do not like it

In D There is no need to prove that u can say NO if number of problematic index is >4 U can take a big number like 1000 and solution will still pass eg:

https://codeforces.me/contest/2233/submission/378004270

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it

    My goat lazypanda actually did binary search on it and found the constant 3350 to TLE :)

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I have done problem C using Graphs. Lets represent each bracket as a node and draw undirected edge between '(' and ')'. It is always good to remove the node with max degree. By doing it k times we find the answer.

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    hmm

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    I thought about the same now I tried to do the contest in a Virtual Participation. The Graph is kind of weird, but you can match the first '(' you find with the first right ')'. Now, if you find a ')' before matching it, it means that it will sum one to the degree of the first '('.

    However, as I could not do that logic by myself as I thought it was kind of incomplete, I just gave up and came to the editorial and tried to implement the idea myself.

    Do you have the submission so I can check if I thought the same?

»
3 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

I rewrite my code 4 times for D :sob:

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Another construction for B: Hardcode for n= 2,3 Rest of cases: Identity permutation, Identity permutation, Shifted identity permutation to the right, Shifted identity permutation to the left.

»
3 months ago, hide # |
Rev. 2  
Vote: I like it +106 Vote: I do not like it

There is another way of showing the claim of E2 (also solve the whole problem):

For any positive integer sequence $$$A$$$ of length $$$N$$$ without duplicate, $$$A$$$ would be a permutation of $$$[1, 2, \ldots, N]$$$ if and only if $$$\sum\limits_{i = 1}^N A_i = \frac{N(N+1)}{2}$$$.

So the problem is reduced to finding the number of ways to permute strings so the sum is $$$\frac{N(N+1)}{2}$$$. Since this is the lower bound of the sum over any positive integer sequence without duplicate, we can relax the condition into minimize the sum and check if it is $$$\frac{N(N+1)}{2}$$$.

The only way to minimize it is to sort strings by frequency of $$$1$$$ bits. Which deduce the final solution in the editorial and also prove why we can permute strings with same number of $$$1$$$ bits arbitrarily.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

377950426

My soln for B was eg. n = 3

"1 2 3" "1 2 3" "2 3 1" <-- (rotate by 1) "1 2 3"

»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

My solution to B: Start with n=2 case, For n>2 — append all numbers 3...n to the right of each 1.

if (n == 2)
    {
        cout << "1 2 2 1 1 2 1 2\n";
        return;
    }
    else
    {
        string a = "1 ";
        for (int i = 3; i <= n; i++)
        {
            a += to_string(i) + " ";
        }
        string res = "";
        res = a + "2 2 " + a + a + "2 " + a + "2";
        cout << res << '\n';
    }
»
3 months ago, hide # |
Rev. 3  
Vote: I like it +16 Vote: I do not like it

With a careful implementation, I solved F 378020300 using Dijkstra’s algorithm in $$$O(d(ab)^2)$$$.

Can it be hacked?

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I thought C was DP? was anyone able to define a DP state which works in O(n^2)

»
3 months ago, hide # |
Rev. 5  
Vote: I like it +1 Vote: I do not like it

Unfortunately I missed some of the cool observations for E2 and overkilled, my solution is follows:

Submission: 377991037

  • Consider DP approach, where DP[d][mask] is number of ways of filling $$$d^{th}$$$ string whereas the previous strings are already filled. $$$mask$$$ denotes the strings which are already used up.
  • One observation, if N is $$$2^{x} - 1$$$ , and with no duplicates, we can permute the strings in any order, Reason: re-arranging the strings in any order can never produce a number > N. So all numbers [1,N] occur.

Idea:

  • First lets fix the top string, (0000...1111) we need to verify that the count of 0s, is correct here.

  • Since any rearrangement of other strings would automatically handle (0000) guys, now the problem reduces to rearrangining the remaining strings such that those starting at (1111) are correctly handled. Similary to traversing a binary trie top down.

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Hey !! Saw your solution for E1 posted in editorial cmmts sections for last edu 191 contest can you elaborate how the idea came i mean there would have been a series of thoughts questions you asked yourself and also can you elaborate your solution a bit more i mean if you are free Thankss!!!!

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

This is some text.

// this is code
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#include <numeric>
#include<map>
#include<set>
#include <queue>
#include<utility>
#define int  long long
using namespace std;
void solve() {
   int n;
   cin >> n;
   vector<int> ans(n*4);
   vector<int> dummy(n);
   for(int i = 0 ; i < n ; i++){
         ans[i] = i+1;
         dummy[i] = i+1;
   }
   for(int i = 0 ; i < n ; i++){
    ans[n+i] = dummy[i];
   }
   for(int i = 0 ; i < n ; i++){
    ans[3*n+i] = dummy[i];
   }
   reverse(dummy.begin(),dummy.end());
   reverse(dummy.begin()+1,dummy.end());
   for(int i = 0 ; i < n ; i++){
    ans[2*n+i] = dummy[i];
   }
   for(int i = 0 ; i < 4*n ; i++) cout << ans[i] <<" ";
   cout << endl;
}


signed main(){
    int t;
    cin >> t;
    while (t--) {
       solve();
    }   
    return 0;
}

an interesting one

»
3 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

In D, checking if the array is arranged correctly after a swap can be done in constant time

ll delta = 0;

// p1 and p2 are the positions to be swapped
if (p1 > 0 && a[p1] != a[p1 - 1]) delta++;
if (p1 < n - 1 && a[p1] != a[p1 + 1]) delta++;
if (p2 > 0 && a[p2] != a[p2 - 1]) delta++;
if (p2 < n - 1 && a[p2] != a[p2 + 1]) delta++;

swap(a[p1], a[p2]);

if (p1 > 0 && a[p1] != a[p1 - 1]) delta--;
if (p1 < n - 1 && a[p1] != a[p1 + 1]) delta--;
if (p2 > 0 && a[p2] != a[p2 - 1]) delta--;
if (p2 < n - 1 && a[p2] != a[p2 + 1]) delta--;

swap(a[p1], a[p2]);

// unique is the number of unique values in the array
// seg is the number of segments with only one value in the array
if (seg - delta == unique) {
    cout << "YES\n";
    return;
}

»
3 months ago, hide # |
Rev. 3  
Vote: I like it 0 Vote: I do not like it

In the $$$O(n)$$$ editorial solution for problem C:

A closing bracket remains unmatched only if, at the moment it is processed, there were more closing brackets than opening brackets before it.

However, for a string such as )))(), the 5th character gets matched although there are more closing brackets that opening brackets proceeding it. I think what is true, instead, is that a closing bracket at index $$$i$$$ is not matched iff

$$$\texttt{pref_open}_i - \texttt{pref_close}_i \lt \texttt{pref_open}_j - \texttt{pref_close}_j \text{ for all } j \lt i.$$$

We can then use that to prove that the total number of unmatched closing brackets is:

$$$\min_i(\texttt{pref_open}_i - \texttt{pref_close}_i) = -\min_i(\texttt{balance}_i)$$$
»
3 months ago, hide # |
Rev. 4  
Vote: I like it +3 Vote: I do not like it
my solve for D
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

What's the definition of pref_open and suff_close in C? I didn't really understand.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

During the open hacking phase, all non-mine submissions show Source: N/A, and clicking Copy also gives N/A. I can view my own submissions normally. I also tested old problem submissions, recent contest submissions, and different users. Same result: other users’ source is always N/A. The announcement says we should have access to copy any solution during the 12-hour hacking phase.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

why question F is so vague and unclear ??

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

tried B for almost 1.5 hour after solving A, wasted 3 pages of my notebook to get an idea, failed horribly, how can i improve in these kinds of problems?

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    These are called Construction Problems. They can often get 'if you see it, you see it'. But with practice, we can learn their pattern. Like this one was more approachable. The key observation was that we only have to solve this problem for n=2 and n=3, then we can extend this solution to any n. This comes with enough practice. To consistently solve Div2-B, I would suggest you solve problems between 1000 — 1200 rating.

»
3 months ago, hide # |
 
Vote: I like it +1 Vote: I do not like it

the shuffle method in B is really interesting — but how are we sure that it works within the given time limit? does there exist a way to calculate the time complexity of functions like these, averaged over a long number of trials, for example?

also, are all permutations generated by shuffle equally likely? how would the time taken change in case the function is biased towards certain permutations? sorry if the questions seem very noob

»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

For problem B this worked for me. but no exact idea why. initially i was thinking of rotating by 1, then by n-1 but that didn't work so i thought may be rotate them by increasing value might work. but no idea how this actually works for all cases. how to prove that this will work always?

void solve() {
    ll n;
    cin >> n;
    vll a(4*n);
    vll v(n);
    for(int i = 1; i <= n; ++i) v[i-1] = i;
    ll k = 0, cnt = 1;
    for(int i = 0; i < 4; ++i){
        for(int j = 0; j < n; ++j) a[k++] = v[j];
        rotate(v.begin(), v.begin() + (cnt % n), v.end());
        cnt++;
    }
    print(a);
}
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

What is the rating system in educational rounds , why rating is not updated yet.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

are ratings not updated yet??

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Educational Codeforces Round 191 (Rated for Div. 2)

Straightforward solution for C

(The ones in the comments look daunting for newbies like me)

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();

        while (t-- > 0) {
            int n = sc.nextInt();
            int k = sc.nextInt();

            String str = sc.next();
            char[] s = str.toCharArray();

            int bal = 0;
            int min_bal = 0;
            int min_ind = -1;

            for (int i = 0; i < n; i++) {
                if(s[i]=='(') bal++;
                else bal--;

                if (min_bal>bal) {
                    min_bal=bal;
                    min_ind=i;
                }
            }

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i <= min_ind; i++) {
                if(k>0 && s[i]=='('){
                    sb.append(1);
                    k--;
                }
                else
                    sb.append(0);
            }

            for (int i = min_ind+1; i < n; i++) {
                if(k>0 && s[i]==')'){
                    sb.append(1);
                    k--;
                }
                else
                    sb.append(0);
            }

            System.out.println(sb);
        }
    }
}
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

E is beautiful.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

for C, can sb tell me where im wrong?

we map +1 to '(' and -1 to ')' and keep a prefix sum, now let e be, the last value of the prefix sum, and m be. the minimum value of the prefixes

now its obvious that max(e, 0) is the number of unmatched '('.

and we can say that the number of unmatched ')' is m because when we hit the minimum its obvious that we have atleast m, ')' unmatched on that prefix and therefor in the whole array, and if at any point there could be more unmatched, m would be lower, so could we say:

cost = n — |min(m, 0)| — max(e, 0)

now we can say that removing a '(' before m decreases both which in the end haas no effect and just wastes k. same reasoning for ')'.

so we try to remove as many ')' as possible, after m. my sol(WA'ed): 377987973

my reasoning seems logical but fails miserably in practice, and could i fix it somehow

  • »
    »
    3 months ago, hide # ^ |
    Rev. 3  
    Vote: I like it 0 Vote: I do not like it
    void solve() {
        int n, k;
        cin >> n >> k;
    
        string s; cin >> s;
    
        int len = 0, o = 0;
    
        for (int i = 0; i < n; i++) {
            o += (s[i] == '(');
    
            if (s[i] == ')' && o > 0) {
                len += 2; o--;
            }
        }
    
        string t(n, '0');
    
        for (int i = 0; i < n; i++) {
            int nl = 0, no = 0;
    
            for (int j = 0; j < n; j++) {
                if (j != i && t[j] == '0') {
                    no += (s[j] == '(');
    
                    if (s[j] == ')' && no > 0) {
                        nl += 2; no--;
                    }
                }
            }
    
            if (nl < len && k > 0) {
                t[i] = '1';  k--;  len = nl;
            }
        }
    
        cout << t << endl;
    }
    
    
»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

Now that open hacking is over, I'll post my alternate solutions since I had an irrational fear of getting hacked

For A I used binary search because I was too lazy to derive the formula for using AI lol: 377924003

Now here's my alternate solution for C:

Spoiler
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

number of transition in F can be further reduced to around $$$10^7$$$ by observing either $$$p$$$ or $$$q$$$ is prime in optimal choices, since if

$$$p = p_1 \times p_2, q = q_1 \times q_2, (2 \leq p_1 \leq p_2, 2 \leq q_1 \leq q_2, p \leq q)$$$

holds, then

$$$\max(p_1, q_1) + \max(p_2, q_2) \leq 2 \max(p_2, q_2) = \max(2p_2, 2q_2) \leq \max(p_1p_2, q_1q_2) = \max(p, q)$$$

So any pairing of two composite number can be decomposed into two "smaller" pairing without worsening the cost.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I hate this. Solution submitted with PyPy got hacked, but the same solution submitted with Python3 passes all tests.

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

i have a better solution for problem b: ~~~~~ void solve() { int n;cin>>n; vectora(4*n); if(n==2){ cout<<2 <<" "<< 1<<" "<< 1<<" " <<2<<" "<< 1<<" "<< 2<<" " <<2 << " "<<1<<endl; return; } int start=0; int m=4*n; int x=1; while(m && x<=n){ a[start]=x; a[start+1]=x; a[start+3]=x;

if(m==4) a[2]=x;
    else a[start+  6 ]=x;
    x++;
    m=m-4;

    start=start+4;


}
for(auto i:a){
    cout<<i<<" ";
}
cout<<endl;
return;

}

signed main() { ios::sync_with_stdio(false); cin.tie(nullptr);

int t;
cin >> t;

while (t--) {
    solve();
}

return 0;

}

~~~~~

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Can somebody help in Problem C, my logic for it:

I made a binary string using the bracket sequence given and counted the '(' which contributes to the cost and gave it 1 in string, and all others are 0,

then, by looking at this cost string, I choose the k characters from this, because only these characters will lower the cost,

and make an ans string from this cost string as: 378013633 but this comes out wrong,

Please correct me and how to solve C

  • »
    »
    3 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    The cost is not only dependent on '('.

    Consider the string "(((((((()" Although there are many '(', only one of them contributes to the cost.

    Additionally, in this case, removing the ')' character is the most efficient way to reduce the cost. Therefore, lowering the cost may require removing both types of characters.

    • »
      »
      »
      3 months ago, hide # ^ |
      Rev. 3  
      Vote: I like it 0 Vote: I do not like it

      In my code, has considered this type of case and specifically counted these '(' for ex: (()()(()) will have the cost string of 010101100, because first '(' is not pairing up.

      so according to suggestion, I should focus on removing these ')' instead of '('?

      • »
        »
        »
        »
        3 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        Due to the nature of the problem, you cannot focus on only one type of bracket. You may have to remove '(', and you may also have to remove ')'

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I did this on b: ~~~~~ rep(i,1,n+1) cout<<i<<' '; rep(i,1,n+1) cout<<i<<' '<<i<<' '; rep(i,1,n) cout<<n-i<<' '; cout<<n; ~~~~~

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

a very easy construction for B:

Solution
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it
Spoiler for Problem B
soln : B
»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

Okay so I did not figure out any of the methods for B, got stuck on B itself, but then found a random pattern that will always satisfy the property given in the problem. The pattern is as follows : 1 2 3 ... n | 2 3 4 ... n 1 | 2 3 4 ... n 1 | 1 2 3 ... n I added the divisions in the sequence for a better clarity in reading, and we can generalize the values of difference in positions for all the numbers, viz. equal to n-1, n and n+1 for i = 2 to n, and 2n-1, n, and 1 for i = 1.

The recursive method to solve this problem is something that should've struck me during the contest, but yeah next time.

Edit : I found a better method to logically get this pattern. Basically [1, 2, 2, 1, 2, 1, 1, 2] is a valid sequence for n = 2, and now we can observe for this that to go from size n to n+1 we simply add the new elements just after the previous largest elements. The properties remain valid as the largest differences grow at the greatest rate and thus the differences can never become equal.

»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

I ended up solving C using a different O(n) greedy based on directly destroying matched pairs and maintaining active bracket structure rather than the pref_open + suff_close observation from the editorial.

I wrote up the idea here if anyone is interested:

https://codeforces.me/blog/entry/154439

378240026

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I forgot that I registered for this contest, what a pity...

However, I've found a solution for B without the need to consider the parity of n.

Implementation
»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

guys i am unable to solve the problem d can anyone explain clearly . i have asked ai to explain but its sloppy explanation made my brain rot

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

It was harder than usual edu div2. But got 3 done anyhow

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I completely missed the construction strategy for problem B, but it turns out that backtracking, albeit an overkill approach for this problem, works in the allotted time constraint. It helps that early placements of integers never fails and each placement can be validated in constant time before recursing.

Here is my solution: 379937279

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

An Intuitive Explanation: Thinking with the Balance Graph (2233C — Cost of a Bracket Sequence)

Instead of staring at algebraic formulas, let us visualize the string as a trajectory on a 2D plane:

  • Start at (0, 0).
  • For each character, if it is '(', move up by 1 (+1). If it is ')', move down by 1 (-1).

Here is the beautiful geometric insight that makes the O(n) solution trivial:

1. Why the Global Minimum (mn) represents Unmatched ')' When we scan from left to right, whenever the graph dips below its previous minimum, it means we have encountered more ')' than '(' can safely shield. Any '(' that appears AFTER a dip cannot save the ')' before it, because brackets can only match forward. Therefore, the global minimum (the lowest valley) represents the absolute bottleneck: the total number of inherently unmatched ')' in the string is exactly -mn. Since every unmatched ')' directly kills one potential pair, the maximum number of pairs we can ever form is bounded by: Max Pairs = total_close + mn.

2. The Magic Split Point (pos) Let 'pos' be the index where the graph hits this global minimum. By definition, 'pos' must be a ')' character. If we cut the string at 'pos', look at what happens to the two sides:

  • To the left of 'pos': The graph ends at its absolute lowest point. This means every single '(' on the left has been completely consumed and paired up by the ')' on the left. There are no leftover '(' here; only a surplus of unmatched ')'.
  • To the right of 'pos': The graph starts at its lowest point and can only go up relative to this baseline. This means every single ')' on the right will find a matching '(' on the right. There are no leftover ')' here; only a surplus of unmatched '('.

3. How to Minimize Pairs with k Deletions Our goal is to minimize the final cost (max pairs), which means we want to maximize the number of unmatched brackets.

  • Left of 'pos': The surplus is unmatched ')'. To preserve this, we should greedily delete '(' from the very beginning. Deleting a '(' prevents it from absorbing a ')', keeping the valley deep.
  • Right of 'pos': The surplus is unmatched '('. To preserve this, we should greedily delete ')' from the very end. Deleting a ')' prevents it from absorbing a '('.

This completely validates the greedy choice of 'pos' and the deletion strategy!

void solve() {
    int n, k;
    cin >> n >> k;
    string s;
    cin >> s;
    
    // Track the trajectory to find the lowest valley (global minimum)
    int c = 0, pos = 0, mn = 0;
    for (int i = 0; i < n; i++) {
        c += (s[i] == '(' ? 1 : -1);
        if (c < mn) {
            mn = c;
            pos = i + 1; // Split right after the lowest valley
        }
    }
    
    string ans(n, '0');
    // Left side: kill '(' from the front to maximize unmatched ')'
    for (int i = 0; i < pos && k; i++)
        if (s[i] == '(') ans[i] = '1', k--;
        
    // Right side: kill ')' from the back to maximize unmatched '('
    for (int i = n - 1; i >= pos && k; i--)
        if (s[i] == ')') ans[i] = '1', k--;
        
    cout << ans << '\n';
}
»
3 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

https://codeforces.me/contest/2233/submission/381280759-- My solution for C

An Intuitive Way to Look at the Problem

When I first looked at this problem, I couldn't really think about stack matching or prefix balances. Instead, I tried to understand how a balanced bracket sequence is actually formed.

Step 1: Looking at a single Regular Bracket Sequence

Consider any single Regular Bracket Sequence (RBS). If we scan it from left to right, there may be moments where we have seen more ) than (. These are the places where some closing brackets are temporarily “waiting” for opening brackets.

Similarly, if we scan from right to left, there may be moments where we have seen more ( than ). These opening brackets.

The important realization is this: A single RBS can only have its imbalance coming from one direction. It cannot simultaneously have unmatched ) on the right and unmatched ( on the left.

Why? Because if both kinds of unmatched brackets existed inside the same RBS, they would eventually match each other, meaning they were never truly unmatched in the first place.

So every RBS is either * right-heavy (extra ) while scanning left to right), or * left-heavy (extra ( while scanning right to left), but never both.

Step 2: What happens when multiple RBSs are placed together? Now imagine the entire string consists of several RBSs placed one after another. Suppose the first RBS is right-heavy. Then the next RBS can again be right-heavy.

Eventually, we encounter the first left-heavy RBS. Now comes the key observation: After the first left-heavy component appears, every RBS after it must also be left-heavy.

Why? Assume the opposite. Suppose after a left-heavy RBS, another right-heavy RBS appears.

The unmatched opening brackets from the left-heavy component and the unmatched closing brackets from the later right-heavy component would meet and form pairs. That means those two parts were actually connected and should have been considered one larger RBS instead of two separate ones.

This is a contradiction.

Therefore, the sequence of components looks like

Right-heavy Right-heavy Right-heavy ... Left-heavy Left-heavy Left-heavy

There can be only one transition from right-heavy to left-heavy. OR simply all being either Right-heavy only or Left-heavy only and no transition.

Step 3: Finding the transition

Now the implementation becomes straightforward. Left to Right Scan Maintain the balance. Whenever the balance becomes negative, record that index.

The last such position is stored as lastRightBracket This marks the end of the right-heavy region.

Right to Left Scan Again maintain the balance, but in reverse. Whenever the reverse balance becomes negative, record that index.

The last recorded position becomes lastLeftBracket This marks where the left-heavy region begins.

Step 4: Constructing the answer

Now the string naturally divides into three regions.

|---- Right-heavy ----|---- Middle ----|---- Left-heavy ----| 0 lastRight lastLeft n-1

Now simply choose brackets greedily.

  • In the right-heavy region, pick opening brackets ( until we have selected k.
  • In the middle region, continue picking any opening brackets (as this transition region is no heavy region i.e nothing outside of it can affect it) until we have selected k.
  • In the left-heavy region, pick closing brackets ) until we have selected k.

Everything else is ignored.

This directly constructs the required answer.

Complexity

Both scans are linear.

  • First scan: O(n)
  • Second scan: O(n)
  • Constructing the answer: O(n)

Overall complexity:

  • Time: O(n)
  • Space: O(n)

Final Thoughts

What I like most about this solution is that it didn’t come from memorizing a known trick or an algo.

Instead, it came from asking a simple question: “Where does the imbalance of each regular bracket sequence actually come from?”

Once I realized that every balanced component can only be imbalanced from one side, the existence of a single transition point became almost obvious.

From there, the implementation naturally followed with just two linear scans.