hdu2838Cow Sorting(樹狀數組+逆序數)
阿新 • • 發佈:2017-06-22
至少 http 個數 範圍 打開 main tdi def esp
題目鏈接:點擊打開鏈接
題意描寫敘述:給定一個長度為100000的數組,每一個元素範圍在1~100000,且互不同樣,交換當中的隨意兩個數須要花費的代價為兩個數之和。
問怎樣交換使數組有序。花費的代價最小?
解題思路:
1、顯然我們知道,要使一個數組有序至少交換的次數(即必需要交換的次數)為數組中的逆序數
2、因為數組的長度比較大所以我們能夠通過樹狀數組來統計結果
此處須要兩個樹狀數組
第一個:記錄小於等於某個值的元素的個數
第二個:記錄小於等於某個值的元素的和
代碼:
#include <cstdio> #include <cstring> #define MAXN 100010 using namespace std; int C[MAXN]; int lowbit(int x) { return x&(-x); } int sum(int pos) { int ret=0; while(pos>0) { ret+=C[pos]; pos-=lowbit(pos); } return ret; } void add(int pos,int v) { while(pos<=100000) { C[pos]+=v; pos+=lowbit(pos); } } long long Ct[MAXN]; long long sumt(int pos) { long long ret=0; while(pos>0) { ret+=Ct[pos]; pos-=lowbit(pos); } return ret; } void addt(int pos,int v) { while(pos<=100000) { Ct[pos]+=v; pos+=lowbit(pos); } } int main() { int n; while(scanf("%d",&n)!=EOF) { memset(C,0,sizeof(C)); memset(Ct,0,sizeof(Ct)); long long ans=0; int x; for(int i=0; i<n; ++i) { scanf("%d",&x); add(x,1); addt(x,x); ans+=((sum(100000)-sum(x))*(long long)x+sumt(100000)-sumt(x));///註意溢出問題 } printf("%I64d\n",ans); } return 0; }
hdu2838Cow Sorting(樹狀數組+逆序數)