求逆序對(介紹+題目)

hewt發表於2021-11-28

介紹

逆序對 - 如果存在l<r,並且a[l]<a[r],則稱為一個逆序對。
在穩定排序情況下,逆序對的個數等於相鄰數交換的次數。(可以說是冒泡的次數)
至於你說你氣泡排序,歸併排序(後面要用)都不太會建議去看看,鄙人的文章
各種排序集合
ps:並不是打廣告,這是為了您好.)逃

個人看法

相信很多人跟 以前的我 一樣認為逆序對不難,歸併排序一下就出來了,多簡單啊!
但我想說,簡單是簡單,但是大部分題目你都看不出來,所以 偶 才寫了這篇文章

題目

P5149 會議座位

題目描述

話說校長最近很喜歡召開全校教職工大會,讓老師們強行聽他裝逼

現在校長在校園網上公佈了一份座位表,\(n\) 位老師從左到右依次排成一行。老師們都對這個座位很滿意。

然而到了開會時,校長不小心把座位表打亂了,老師們很不滿。老師們並不在意自己的位置變了多少,但如果有一對老師 \(a\)\(b\),他們原來的座位是 \(a\)\(b\) 左邊,現在變成了 \(a\)\(b\) 右邊,那麼這一對老師便會有一單位不滿值。

校長想知道這些老師的總不滿值是多少。

輸入介紹

第一行一個正整數 \(n\),為 \(n\) 位老師。

第二行有 \(n\) 個字串,每個字串代表老師的名字(大小寫敏感)。這一行代表原來的座位表。

第三行有 \(n\) 個字串,代表打亂後的座位表。

輸出介紹

一行,一個正整數,表示老師們的總不滿值。

輸入輸出樣例

樣例1:
3                                                                    1
Stan Kyle Kenny                                                      
Kyle Stan Kenny                                                      

樣例2:
5                                                                    3
A B C D E
B A D E C

解析

只要看清本質就會了,就是求逆序對
用歸併排序就可以了

程式

由於個人 馬 蜂 不好看所以用一個"盆友"的

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+5;
string s;
int n,a[N],b[N];
long long ans;
map<string,int>m;

void merge_sort(int left,int right)
{
	if(left>=right) return;
	int mid=(right-left)/2+left;
	merge_sort(left,mid);
	merge_sort(mid+1,right);
	int i=left,j=mid+1,k=left;
	while(i<=mid&&j<=right)
	{
		if(a[i]<a[j]) b[k++]=a[i++];
		else b[k++]=a[j++],ans+=mid-i+1;
	}
	while(i<=mid) b[k++]=a[i++];
	while(j<=right) b[k++]=a[j++];
	for(int i=left;i<=right;i++)
		a[i]=b[i];
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		m[s]=i;
	}
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		a[m[s]]=i;
	}
	merge_sort(1,n);
	printf("%lld",ans);
	return 0;
}

相關文章