1. 程式人生 > >luoguP1774 最接近神的人_NOI導刊2010提高(02)x

luoguP1774 最接近神的人_NOI導刊2010提高(02)x

event using 現在 class 開啟 str int 圖案 cout

P1774 最接近神的人_NOI導刊2010提高(02)

題目描述

破解了符文之語,小FF開啟了通往地下的道路。當他走到最底層時,發現正前方有一扇巨石門,門上雕刻著一幅古代人進行某種活動的圖案。而石門上方用古代文寫著“神的殿堂”。小FF猜想裏面應該就有王室的遺產了。但現在的問題是如何打開這扇門……

仔細研究後,他發現門上的圖案大概是說:古代人認為只有智者才是最容易接近神明的。而最聰明的人往往通過一種儀式選拔出來。儀式大概是指,即將隱退的智者為他的候選人寫下一串無序的數字,並讓他們進行一種操作,即交換序列中相鄰的兩個元素。而用最少的交換次數使原序列變成不下降序列的人即是下一任智者。

小FF發現門上同樣有著n個數字。於是他認為打開這扇門的秘訣就是找到讓這個序列變成不下降序列所需要的最小次數。但小FF不會……只好又找到了你,並答應事成之後與你三七分……

輸入輸出格式

輸入格式:

第一行為一個整數n,表示序列長度

第二行為n個整數,表示序列中每個元素。

輸出格式:

一個整數ans,即最少操作次數。

輸入輸出樣例

輸入樣例#1:
4
2 8 0 3
輸出樣例#1:
3
   樣例說明:開始序列為2 8 0 3,目標序列為0 2 3 8,可進行三次操作的目標序列:
    1.Swap (8,0):2  0  8  3
    2.Swap (2,0):0  2  8  3
    3.Swap (8,3):0  2  3  8

說明

對於30%的數據1≤n≤10^4。

對於100%的數據1≤n≤5*10^5;

-maxlongint≤A[i]≤maxlongint。

思路:

  在歸並排序的時候順便搞一下逆序對.

坑點:

  ans+=m-i+1;///是已排好序的區間形成的逆序對個數

代碼:

技術分享
#include <iostream>
#define LL long long

using namespace std;

const int M = 500010;
int n;
int num[M],tmp[M];
LL ans;

void gsort(int l,int r) { int m=(l+r)>>1; int i=l,cnt=0,j=m+1; while(i<=m && j<=r) { if(num[i]<=num[j]) tmp[cnt++]=num[i++]; else { ans+=m-i+1;///已排好序的區間形成的逆序對個數 tmp[cnt++]=num[j++]; } } while(i<=m) tmp[cnt++]=num[i++]; while(j<=r) tmp[cnt++]=num[j++]; for(int i=0;i<cnt;i++) num[l+i]=tmp[i]; } void sorts(int l,int r) { if(l<r) { int m=(l+r)>>1; sorts(l,m); sorts(m+1,r); gsort(l,r); } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>num[i]; sorts(1,n); cout<<ans; return 0; }
View Code

luoguP1774 最接近神的人_NOI導刊2010提高(02)x