[USACO10NOV]奶牛的圖片Cow Photographs
阿新 • • 發佈:2018-06-02
set 最小 farmer target cout lan sdi open tom
題目描述
Farmer John希望給他的N(1<=N<=100,000)只奶牛拍照片,這樣他就可以向他的朋友炫耀他的奶牛.
這N只奶牛被標號為1..N. 在照相的那一天,奶牛們排成了一排.其中第i個位置上是標號為 ci(1<=ci<=N)c_i(1<=c_i<=N)ci?(1<=ci?<=N) 的奶牛.
對於奶牛的站位,Farmer John有他自己的想法. FJ是這麽想的,標號為i(1<=i<=n-1)的奶牛只能站在標號為i+1的奶牛的左邊,而標號為N的奶牛只能站在標號為1的奶牛的左邊.當然,沒有牛可以站在隊列中最左邊的奶牛的左邊了.也就是說,最左邊的奶牛編號是隨意的.
這些奶牛都非常的餓,急切的希望吃到FJ承諾的在拍照後的大餐,所以FJ想盡快的拍照.奶牛們的方向感非常的不好,所以FJ每一分鐘只可以選擇相鄰的兩只奶牛然後讓他們交換位置.FJ最小需要多少時間就能使奶牛站成一個可以接受的序列?
比方說一個有5只奶牛的例子,一開始序列是這樣的: 左邊 右邊 3 5 4 2 1
第一分鐘,FJ可以交換第二隊奶牛(即5和4),交換後的隊列: 3 4 5 2 1
第二分鐘,FJ交換最右邊的一對,序列變成這樣: 3 4 5 1 2
這樣,只用了2分鐘,就是序列變為了一個FJ所希望的序列.
輸入輸出格式
輸入格式:第1行:一個單獨的數N 第2到n+1行:第i+1行上的數表示站在第i的位置上的奶牛的編號(即 cic_ici? ).
一個整數,表示是奶牛的序列變為一個合法的序列的最小花費時間.
輸入輸出樣例
輸入樣例#1:5 3 5 4 2 1輸出樣例#1:
2
提交地址:Luogu4545
眾多USACO搜索題中的一股小清流;
剛看題:裸的逆序對渺渺渺渺;
笑容逐漸凝固:woc這沒我想的那麽簡單...
我們的逆序對可以解決從1~n的排列問題, 但是這道題顯然不是從1~n的排列;
那怎麽辦呢?
例如234561的序列, 逆序對個數為5, 這表明我們要換5次,是嗎?顯然不是, 我們一次都不用換;
那我們該怎樣考慮這個問題呢?
我們可以把1想象成7!這樣逆序對為0,且滿足題意;
再舉個例子, 3456721;原始逆序對為10個;我們把1想象成8, 逆序對為5;
我們把2想象成9,逆序對為1;
意思是,我們從小到大枚舉一個數假設它最大, 意思是它就是序列的一個結尾;
那我們怎樣快速地求出修改之後的逆序對的數量呢?
顯然最小的數產生的逆序對數量等於pos[i]-1, 就是它位置減一;
它成為最大值之後會增加n-pos[i]個新的逆序對;
所以我們可以先求出原先序列的逆序對, 然後枚舉最小的數為最大數, 修改逆序對的數量, 然後取min;
代碼奉上:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 inline int read() 7 { 8 int res=0;bool fl=0;char ch=getchar(); 9 while(!isdigit(ch)){if(ch==‘-‘)fl=1;ch=getchar(); 10 }while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch-‘0‘);ch=getchar(); 11 }return fl?-res:res; 12 } 13 14 int n; 15 int a[100010]; 16 int pos[100010]; 17 18 int t[1000010]; 19 inline int lowbit(int x){return x & -x;} 20 21 inline void add(int x, int y){while(x <= n){t[x]+=y;x+=lowbit(x);}} 22 23 inline int query(int x){int ans=0;while(x!=0)ans+=t[x], x-=lowbit(x);return ans;} 24 25 long long ans; 26 long long best; 27 28 int main() 29 { 30 n = read(); 31 for (register int i = 1 ; i <= n ; i ++) a[i] = read(), pos[a[i]] = i; 32 33 for (register int i = n ; i >= 1 ; i --) 34 { 35 ans += query(a[i] - 1); 36 add(a[i], 1); 37 } 38 39 best = ans; 40 41 for (register int i = 1 ; i <= n ; i ++) 42 { 43 best = best - (pos[i] - 1) + (n - pos[i]); 44 ans = min(ans, best); 45 } 46 cout << ans << endl; 47 return 0; 48 }
[USACO10NOV]奶牛的圖片Cow Photographs