Official

F - Transpose Editorial by en_translator


Thinking about the whole procedure may be puzzling, so it is a good idea to decompose it into multiple easy operations.

First, let us determine the resulting case of each character.
This is not so difficult, as it can be determined as follows:

  • If a character is surrounded by an even number of parenthesis pairs, its case does not flip.
  • If a character is surrounded by an odd number of parenthesis pairs, its case flips.

After flipping the case according to rules, we no longer have to care about the case.

Now what we need is the following operation:

  • For each consecutive substring starting and ending with ( and ), respectively, remove ( and ) and reverse it.

The resulting string can be found by the following recursion:

  • Define a recursive function \(f(l,r,d)\).
  • If \(d = 0\), iterate the \(l\)-th, \((l+1)\)-th, \(\dots\), and \(r\)-th characters. Whenever an English alphabet is found, print it.
    • Whenever you found ( at the \(l_u\)-th position, let \(r_u\) be the position of the corresponding ).
    • Call \(f(l_u+1,r_u-1,1)\), and then resume the process from the \((r_u+1)\)-th character. (Note that we will have finished processing the \(l_u\)-th through \(r_u\)-th characters at this point.)
  • If \(d = 1\), iterate the \(r\)-th, \((r-1)\)-th, \(\dots\), and \(l\)-th characters. Whenever an English alphabet is found, print it.
    • Whenever you found ) at the \(r_u\)-th position, let \(l_u\) be the position of the corresponding (.
    • Call \(f(l_u+1,r_u-1,0)\), and then resume the process from the \((l_u-1)\)-th character.

Correspondence between ( and ) can be precalculated in a total of \(O( |S| )\) time.
All that left is to call \(f(1,|S|,0)\) to get correct answer for this problem in a total of \(O(|S|)\) time.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

char flp(char c){
  if('A'<=c && c<='Z'){
    return (c-'A'+'a');
  }
  return (c-'a'+'A');
}

string s;
vector<int> mch;

void f(int l,int r,int d){
  if(d==0){
    while(l<=r){
      if(s[l]=='('){
        f(l+1,mch[l]-1,1);
        l=mch[l];
      }
      else{
        cout << s[l];
      }
      l++;
    }
  }
  else{
    while(l<=r){
      if(s[r]==')'){
        f(mch[r]+1,r-1,0);
        r=mch[r];
      }
      else{
        cout << s[r];
      }
      r--;
    }
  }
}

int main(){
  cin >> s;
  int l=s.size();
  mch.resize(l);
  for(auto &nx : mch){nx=-1;}

  int h=0;
  vector<int> stk;
  for(int i=0;i<l;i++){
    if(s[i]=='('){
      stk.push_back(i);
      h++;
    }
    else if(s[i]==')'){
      mch[i]=stk.back();
      mch[stk.back()]=i;
      stk.pop_back();
      h--;
    }
    else if(h%2){
      s[i]=flp(s[i]);
    }
  }

  f(0,l-1,0);
  return 0;
}

posted:
last update: