公式

F - Concat (2nd) 解説 by physics0523

別解の補足2

特定の要素を \(O(N)\) 回読ませる事態をコードが読めない状態で引き起こすことは非常に困難です。
今回の問題では、 C++ の sort を使った場合でも、入力を予め shuffle することで、クイックソートの pivot を乱択したような状態になり撃墜が困難なコードが出来上がります。

以下のコードは高い確率で AC しますが、 28 行目をコメントアウトして提出すると TLE することが分かります。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

bool comp(const string &x,const string &y){
  return (x+y < y+x);
}

string concat(vector<string> &s){
  string res="";
  for(auto &nx : s){ res+=nx; }
  return res;
}

int main(){
  std::random_device seed_gen;
  std::uint32_t seed = seed_gen();
  std::mt19937_64 engine(seed);

  int t;
  cin >> t;
  while(t--){
    int n;
    cin >> n;
    vector<string> s(n);
    for(auto &nx : s){cin >> nx;}

    shuffle(s.begin(),s.end(),engine);
    sort(s.begin(),s.end(),comp);

    if(n==2){
      cout << s[1]+s[0] << "\n";
      continue;
    }
    
    bool ok=false;
    for(int i=1;i<n;i++){
      if(s[i-1]+s[i] == s[i]+s[i-1]){ok=true; break;}
    }
    if(ok){
      cout << concat(s) << "\n";
      continue;
    }

    swap(s[n-1],s[n-2]);
    string c1=concat(s);
    swap(s[n-1],s[n-2]);
    swap(s[n-2],s[n-3]);
    cout << min(c1,concat(s)) << "\n";
  }
  return 0;
}

投稿日時:
最終更新: