1. 程式人生 > >HDU 6318 Swaps and Inversions(歸併排序 || 樹狀陣列)題解

HDU 6318 Swaps and Inversions(歸併排序 || 樹狀陣列)題解

題意:一個逆序對罰錢x元,現在給你交換的機會,每交換任意相鄰兩個數花錢y,問你最少付多少錢

思路:最近在補之前還沒過的題,發現了這道多校的題。顯然,交換相鄰兩個數逆序對必然會變化+1或者-1,那我們肯定是-1操作。那麼顯然問題就變成了求逆序對數*min(x,y)。樹狀陣列求逆序對數。

程式碼:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include
<cstring> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 100000 + 10; const int seed = 131; const ll MOD = 100000007; const int INF = 0x3f3f3f3f; int a[maxn], b[maxn], node[maxn]; int lowbit(int x){ return x&(-x); } void update(int
x){ for(int i = x; i < maxn; i += lowbit(i)) node[i]++; } ll query(int x){ ll ret = 0; for(int i = x; i > 0; i -= lowbit(i)) ret += node[i]; return ret; } int main(){ int n, x, y; while(~scanf("%d%d%d", &n, &x, &y)){ ll ans
= 0; memset(node, 0, sizeof(node)); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(b + 1, b + n + 1); for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; for(int i = n; i >= 1; i--){ ans += query(a[i] - 1); update(a[i]); } printf("%lld\n", min(x, y) * ans); } return 0; }