/*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 只需要考慮左右兩段之間造成的逆序對...