ある種の建設問題について。いつでも構築できない状況を見つけて、その構築について考える
この問題では、このkが最小構築時間と最大構築時間の間に構築できる場合、次のように構築できます。
ここでの問題は、最小値と最大値を見つける方法です。タイトルの反転については、彼を交換と見なすこともできます。したがって、最小のケースは、実際には1回の交換、つまり逆順のペアの数です。
最大の状況は、交換可能なすべてのアイテムを毎回交換することです。まず、他のチームの数に関係なく、交換がない場合、つまり交換する必要がある場合、各親族は相対である必要があると考えることができるため、交換可能なすべてが各交換に最適です。
それでは、最小値から最大値まで回数をゆっくりと変更する方法を検討してください。
たとえば、私は3つのポジションを1 3 5交換することができると思っていたはずです。
最初に1 3を交換し、次に5を交換して1回正常に拡張します
これに従って構築できる限り。
最後の交換から始めることを検討していますが、実際には最初の交換から始めることもできますが、これは書くのがより複雑です。
次に、元の最小グループの最後のビットを取り出して、新しいグループに変更します。グループがなくなったことが判明した場合は、前のグループに移動します。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <map> #include < string > #include <vector> using namespace std; typedefベクトル < int > VI; const int N = 3000010 ; int n、k; 文字列s; int tot、idx、cnt; ベクトル < int > ans [N]; int main(){ cin >> n >> k; cin >> s; int i、j; while(1 ){ for(i = 0 ; i <(int)s.size()- 1 ; i ++ ){ if(s [i] == ' R ' && s [i + 1 ] == ' L ' ){ ans [idx] .push_back(i); cnt ++ ; } } もし(ANS [IDX] .empty()) ブレーク。 if(idx> = k){ cout<<" -1 " << endl; 0を返し ます。 } idx ++ ; for(auto x:ans [idx- 1 ]){ swap(s [x]、s [x + 1 ]); } } if(k> cnt){ cout <<- 1 << endl; 0を返し ます。 } int m = idx- 1 ; for(i = k- 1 ; i> = 0 ; i -- ){ if(ANS [M] .empty()) M - 。 if(!ans [i] .empty()) break ; ans [i] .push_back(ans [m] .back()); ans [m] .pop_back(); } for(i = 0 ; i <k; i ++ ){ printf(" %d \ n "、(int )ans [i] .size()); for (auto x:ans [i]){ printf(" %d "、x + 1 ); } printf(" \ n " ); } 戻る 0 ; }