日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj6307-安排【归并排序】

發布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj6307-安排【归并排序】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


題目大意

一個目前序列,一個目標序列,每次可以選擇一個區間交換區間最大值和最小值。

詢問在345678345678345678步內將目前序列轉換回目標序列的方案(輸出該方案)。


解題思路

我們考慮歸并排序,對于兩個升序的序列,我們考慮如何合并為一個序列。

我們從中間往兩邊擴張,我們發現在我們可以找到一個kkk使得任意x≤kx\leq kxkamid?k>amid+k+1a_{mid-k}>a_{mid+k+1}amid?k?>amid+k+1?
我們找到最大的kkk并讓i=mid?k,j=mid+k+1i=mid-k,j=mid+k+1i=mid?k,j=mid+k+1這時我們就有這樣的

我們就有這樣的一個序列,我們考慮將i~Midi\sim MidiMidMid+1~jMid+1\sim jMid+1j翻轉(顯然可以做到)

然后再將i~ji\sim jij這段進行翻轉就有

然后這個時候必定有L~iL\sim iLi中任意一個數都小于等于j~Rj\sim RjR中的數。

所以這個時候我們在將L~MidL\sim MidLMidi?1i-1i?1為新的MidMidMid再次進行新的排序,然后Mid~RMid\sim RMidRjjj為新MidMidMid再次進行排序即可。

這時我們發現對于一次排序需要的次數約為nlog?2n2\frac{n\log^2 n}{2}2nlog2n?,可以通過本題。


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=5000; int n,a[N],x[N<<7],y[N<<7],tot,cnt; void solve(int l,int mid,int r) {if(mid<l||mid>=r||l==r) return;int i=mid,j=mid+1;while(i>l&&j<r&&a[i-1]>a[j+1]) i--,j++;if(i[a]>j[a]){for(int k=i,p=mid;k<p;k++,p--)swap(k[a],p[a]),x[++tot]=k,y[tot]=p;for(int k=mid+1,p=j;k<p;k++,p--)swap(k[a],p[a]),x[++tot]=k,y[tot]=p;for(int k=i,p=j;k<p;k++,p--)swap(k[a],p[a]),x[++tot]=k,y[tot]=p;solve(l,i-1,mid);solve(mid+1,j,r);}return; } void Merge(int l,int r) {if(l==r) return;int mid=(l+r)/2;Merge(l,mid);Merge(mid+1,r);solve(l,mid,r);return; } int main() {freopen("swap.in","r",stdin);freopen("swap.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&i[a]);Merge(1,n);cnt=tot;for(int i=1;i<=n;i++)scanf("%d",&i[a]);Merge(1,n);printf("%d\n",tot);for(int i=1;i<=cnt;i++)printf("%d %d\n",x[i],y[i]);for(int i=tot;i>cnt;i--)printf("%d %d\n",x[i],y[i]); }

總結

以上是生活随笔為你收集整理的jzoj6307-安排【归并排序】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。