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

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

lld 最小 sample clu ++ 輸入輸出格式 ace orange ons

題目描述

破解了符文之語,小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。

註意,是求逆序對,不需要去重,註意到sort的符號判斷!!!

AC代碼如下:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5*100000+5;
struct p{
    int id,num;
    bool operator <(const p &aa) const {
    if(num==aa.num) return id<aa.id;
    return num<aa.num;}
}a[N];
int pos[N],n,c[N];
long
long ans; long long sum(int x) { long long res=0; while(x>0) res+=c[x],x-=(x&-x); return res; } void add(int x) { while(x<=n) c[x]++,x+=(x&-x); return; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i].num),a[i].id=i; sort(a+1,a+n+1); for(int i=1;i<=n;i++) pos[a[i].id]=i; for(int i=1;i<=n;i++) ans+=sum(n-pos[i]+1),add(n-pos[i]+1); printf("%lld",ans); return 0; }

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