懷念一下歸併 逆序對

2022-05-15 23:24:53 字數 1785 閱讀 2086

/*

codevs 4163 神犇與逆序對

*/#include

#define ll long long

#define maxn 1000010

using

namespace

std;

ll n,a[maxn],b[maxn],ans;

ll init()

returnx;}

void

merge_sort(ll l,ll r)

else b[k++]=a[i++];

}while(i<=mid)b[k++]=a[i++];

while(j<=r)b[k++]=a[j++];

for(ll i=l;i<=r;i++)a[i]=b[i];

}int

main()

/*

/*

codevs 3286 火柴排隊

首先要知道兩點 1:兩列火柴高度排名大小相同時排列答案最優 2:移動兩個序

列和移動乙個序列步數一樣

證明嘛 自己想吧 ^ ^ 假設我們只移動第二個序列 消耗步數就是求下逆序對

現在的問題就是求出第二個序列需要怎麼移動

求逆序對我們想到用歸併排序 那麼移動的目標就是有序序列1-n

怎麼和「兩列火柴高度排名大小相同」聯絡起來呢

這樣 我們維護a1 a2 p1 p2幾個序列

a1[i]=j:原序列1中i位置處的高度排名 a2同理

p1[i]=j:原序列1中高度排名i的位置

那p1[a2[i]]就是原序列2中i位置處的高度排名那麼大的在1中的位置

我們把這個位置記在p2[i]中 那就是需要把i移動到p2[i] 也就是逆序對的個數

*/#include

#include

#include

#include

#define mod 99999997

#define maxn 2000020

using

namespace

std;

intn,a1[maxn],a2[maxn],p[maxn],l[maxn],w[maxn];

long

long

ans;

struct

node

s1[maxn],s2[maxn];

intinit()

returnx;}

int cmp(const node &x,const node &y)

void merge(int l,int

r)

else w[k++]=p[i++];

}while(i<=mid)w[k++]=p[i++];

while(j<=r)w[k++]=p[j++];

for(int i=l;i<=r;i++)p[i]=w[i];

}int

main()

for(int i=1;i<=n;i++)

sort(s1+1,s1+1+n,cmp);

sort(s2+1,s2+1+n,cmp);

for(int i=1;i<=n;i++)

for(int i=1;i<=n;i++)

l[a1[i]]=i;

for(int i=1;i<=n;i++)

p[i]=l[a2[i]];

merge(

1,n);

printf(

"%d\n

",ans);

return0;

}

歸併求逆序對

求這個逆序對只需要在歸併排序的 中加一句即可。感覺自己有點說不清楚,隨手附上別人的詳細解釋,請戳 詳細介紹 include include includeusing namespace std int a 1000000 int b 1000000 int sum 0 void merge int ...

記錄一下歸併演算法

歸併排序 這是採用分治法的一種典型應用 也就是分治替換的原則,對乙個序列進行分治,然後使其有序,使其有序的關鍵便是對分組後的序列再次分治,一直如此到最後進行比較替換 遞迴 然後歸併成乙個有序序列 將2個序列進行比較交換的原理是採用雙指標方法,在開始的時候,同時指向2個序列的頭節點 然後預留出乙個2個...

逆序對 (歸併排序)

逆序對的nlogn方法,改進後的歸併排序 給定排列p,求排列的逆序對數量。p的長度 100000。要求o nlogn 定義歸併排序過程merge l,r merge l,r merge l,mid merge mid 1,r count l,mid,mid 1,r 只需要考慮左右兩段之間造成的逆序對...