「CCO 2018 Day2」Flop Sorting 题解
Solution
并没有想到分治,我果然是个屑。
我们考虑分治,那么问题就是如何合并两个有序子段。不难发现,一定是前一段的后缀移到后面去,后一段的前缀移到前面去,所以我们可以两段先反转,就变成了一段连续的下降子序列,再整体反转,那么又变成了子问题,继续分治即可。
用了一点小技巧卡到了LOJ rank1。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 5005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n,a[MAXN],b[MAXN];
#define pii pair<int,int>
vector <pii> ans,Ans;
void fuckit (int l,int r){ans.push_back ({l,r}),swap (a[l],a[r]);}
void merge (int l,int r){
if (l >= r) return ;
bool flg = 1;
for (Int i = l;i < r;++ i) if (a[i] > a[i + 1]){flg = 0;break;}
if (flg) return ;
int mid = l;
while (a[mid] < a[mid + 1]) ++ mid;
for (Int i = l;i <= r;++ i) b[i] = a[i];
nth_element (b + l,b + mid,b + r + 1);
int k1 = l,k2 = r;
while (a[k1] <= b[mid]) k1 ++;
while (a[k2] > b[mid]) k2 --;
for (Int i = k1,j = mid;i < j;++ i,-- j) fuckit (i,j);
for (Int i = mid + 1,j = k2;i < j;++ i,-- j) fuckit (i,j);
for (Int i = k1,j = k2;i < j;++ i,-- j) fuckit (i,j);
merge (l,mid),merge (mid + 1,r);
}
void divide (int l,int r){
if (l >= r) return ;
int mid = l + r >> 1;
divide (l,mid),divide (mid + 1,r),merge (l,r);
}
signed main(){
read (n);
for (Int i = 1;i <= n;++ i) read (a[i]);
divide (1,n),Ans = ans,ans.clear ();
for (Int i = 1;i <= n;++ i) read (a[i]);
divide (1,n);for (Int i = ans.size() - 1;~i;-- i) Ans.push_back (ans[i]);
write (Ans.size()),putchar ('\n');
for (Int i = 0;i < Ans.size();++ i) write (Ans[i].first),putchar (' '),write (Ans[i].second),putchar ('\n');
return 0;
}