牛客網多校第五場 inv (思維+逆序)

鏈接:https://www.nowcoder.com/acm/contest/143/D
來源:牛客網
 

Kanade has an even number n and a permutation b of all of the even numbers in [1,n]

Let a denote an array [1,3,5....n-1] , now you need to find a permutation of [1,n] satisfy both a and b are subsequence of it and minimize the number of inverse pair of it.

 

輸入描述:

The first line has a positive even integer n

The second line has n/2 positive even integers b[i]

輸出描述:

Output the number of inverse pair of the permutation you find.

示例1

輸入

複製

6
2 6 4

輸出

複製

2

說明

[1,2,3,5,6,4]

題意:

給定一個【1,n】裏所有偶數的排列,b,其中n爲偶數,現在有數組a = 【1,3,5,7,....n-1】,現在要求歸併a,b使得逆序對數量最少。

思路:

例如    8 6 4 2

我們考慮每個奇數如何放置。

對於7來說,我們考慮比7大的數,那麼就只有8一個,如果我們把7放在8前面,那麼7將不會與比她大的數產生逆序。

可是我們還要考慮她和比她小的數產生逆序,那麼考慮8的後面,若有比7小的數,那麼逆序++,並且由7產生的逆序最多有一個,因爲我們總可以把7放在最後。

現在考慮5,比5大的數就有兩個了,那麼由5產生的逆序最多爲兩個。我們考慮 8 6 的後面,如果沒有比5小的數,可以把5放在8,6前面,逆序爲0,若果有一個逆序爲1,否則取最多2.

由上面的分析可以看出,對於每個奇數,我們考慮比她大的偶數的個數假設爲x,那麼該奇數最多產生x對逆序,如果,比他大的數可以向後匹配比這個奇數小的數,假設可以匹配出y對來,那麼該奇數逆序的貢獻爲min(x,y);

對於 8 6 4 2 來說考慮5    (8,4),(6,2) 兩對,8,6有兩個,故而 x=y=2;

那麼如何統一計算結果呢????

如果單單考慮5, 遇到8>5 我們可以先存起來,6>5存起來,4<5 取出來8湊一對,2<5取出6湊一對。

設最終逆序爲ans = 0;

若統一考慮所有情況。我們可以考慮優先隊列來存,

8入隊              8 並不小於對中最大值繼續

6入隊              6 < 8 考慮(8,6)這個對可以使7的逆序加一      ans++

                       又因爲對於7來說8只能向後匹配一次已經用了,可是對於小於6的數來說(8,6)的匹配對他們沒有任何影響,那                         8 該何去何從 ? 很簡單,只要扔掉8,加入一個6就好了,6 肯定不會對7的結果產生影響了,但是可以對剩下的                           產生影響。

                       此時隊列就有 6 6,兩個6

4入隊             4 < 6 一個6出隊5這個逆序加一    ans++;

2入隊             2 < 6 一個6出隊3,5逆序加一     ans+=2;

emmmmm 代碼就很簡單了,,,

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int a[maxn],tree[maxn];
int n;

int lowbit(int x)
{
	return x&(-x);
}

void add(int x,int v)
{
	for(;x <= n; x+=lowbit(x))
	    tree[x]+=v;
}

int sum(int x)
{
	int ans = 0;
	for(;x >= 1; x-=lowbit(x))
    	ans+=tree[x];
    return ans;
}
int main()
{
	scanf("%d",&n);
	for(int i = 0; i < n/2; i++)
	{
		scanf("%d",&a[i]),a[i]/=2;
	}
	long long ans = 0;
	for(int i = 0; i < n/2; i++)
	{
		ans+=i-sum(a[i]),add(a[i],1);
	}
	priority_queue<int>pq;
	for(int i = 0; i < n/2; i++)
	{
		pq.push(a[i]);
		if(pq.top() > a[i])
		{
			ans += pq.top()-a[i];
			pq.pop();
			pq.push(a[i]);			
		}
	}
	cout << ans <<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章