test 排序(二分答案)

2021-07-24 14:10:43 字數 1402 閱讀 1283

題解:二分答案。

這道題貌似是某年ioi的弱化版。

有乙個非常厲害也非常好用的結論:對於遊戲的乙個形如「ababababa.."的操作序列,在所有a操作不變得前提下,可以找到乙個形如」aaaaabbbbb"的操作序列,使兩個序列作用於同乙個排列的效果相同。

有了這個結論的基礎這個題就好做多了。問題就轉化成了最少需要幾次操作將序列變成公升序(可以交換不相鄰的,如果只能交換相鄰的就變成了樹狀陣列求逆序對)

這個需要怎麼搞呢?我們可以從前向後掃,如果當前位置的數不是應該在這個位置的數,就找到應該在這個位置的數,然後將其交換,最終交換了幾次最少的操作次數就是幾。

但是還有別的方法:

以5 4 3 2 1 為例

我們可以發現5,1雖然不在自己應該在的位置,但是如果把它們兩個看成整體,對於整個序列來說它們佔據了排好序後5,1應該在的位置,所以對於整個序列來說是有序的,它們只是自身內部無序而已。5應該到1處,1應該到5處,形成了乙個迴圈,所以可以將它們抽象成乙個環,環內換序就可以了。(下面把這種環稱為迴圈節) 

對於乙個含有n個元素的迴圈節來說,要使其有序,要交換n-1次(前面都排好了,最後乙個數自然有序就不用排了)。 

上例中3在原本就在的位置,可以看成乙個元素的迴圈節。 

我們可以推斷出有乙個迴圈節,就可以少交換一次,因為n個元素的迴圈節,只需交換n-1次即可有序。 

那麼對於整個序列來說,最少交換次數為 元素總數-迴圈節個數。那麼例子中的答案就是2.

然後這道題其實就只需要二分答案然後判定了。

#include#include#include#include#include#define n 600003

using namespace std;

int x[n],y[n],a[n],b[n],pos[n],n,m;

bool pd(int num)

if (t<=num) return true;

return false;

}int main()

printf("%d\n",ans);

}

#include#include#include#include#include#includeusing namespace std;

const int n=610000;

int n,m,i,a[n],s[n],x[n],y[n],vis[n];

int check()

{ int ret=0;

memset(vis,0,sizeof(vis));

for (int i=0;i>1;

for (i=0;i

二分查詢與二分答案

主要用於在乙個單調的函式中查詢某值 連續函式的情況 若當前查詢的區間是 l,r 查詢的值是 y 函式單增 設 mid l r 2 若 f mid y 則 l mid,否則 r mid 直至 r l eps 當前查詢的區間是 l,r 查詢的值是 y 函式單增 設 mid l r 2 若 f mid y...

二分查詢和二分答案

1.解釋 優點 查詢速度快。缺點 待查表為有序表。4.時間複雜度 o log n 5.示例 p2249查詢 include include using namespace std long long n,m,a 1000005 b 100005 l,r,mid,cnt,x intmain for i...

二分與二分答案學習

判斷left,mid,right的符號進行區間的精確。如下為遞迴二分求零點的操作 double find zero point double left,double right,double precesion double mid right left 2 if f mid 0 if f mid ...