HDU-6318 Swaps and Inversions(雜湊+逆序數)
阿新 • • 發佈:2019-02-06
求逆序數的方法:
a[i] 3 2 1 5 4
ind:1 2 3 4 5
1)樹狀陣列
當i=1,查詢1 - a[i]有幾個存在,即在i之前輸入 ,且值小於a[i] ,那麼這些數是非逆序數個數。累加最後n*(1+n)/2 - cnt 求得
2)線段樹
當i= 1時,查詢a[i]-n 有幾個存在,即在i之前輸入的 ,切值大於a[i],那麼這些數就是逆序數。 也可按1)方式做
雜湊:
由於輸入包含負數,而陣列的下標不允許有負數,那麼必須重新給 a[i] 一個編號, 且新編號的大小關係不能變,最小的還是最小的。
for(int i=1;i<=n;i++) { scanf("%d",&node[i].date); node[i].ind = i; } sort(node+1,node+n+1,cmp); // 按date從小到大排序 hash[node[1].ind] = 1; int cnt = 2; for(int i=2;i<=n;i++) { if(node[i].date == node[i-1].date) hash[node[i].ind] = cnt; else hash[node[i].ind] = cnt++; } //這樣a[i]被賦予了新的非負值
code:
#include<stdio.h> #include <cstdio> #include<fstream> #include<string> #include <bitset> #include<iostream> #include<stdlib.h> #include<map> #include<vector> #include<stack> #include <algorithm> #include <cstring> //#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mmax = 1e5 + 5; const int mod = 9901; int dp; int ans[mmax],ans1[mmax]; struct da { int date; int num; bool operator <(const da&b)const { return date<b.date; } } a[mmax]; int lowbit(int x) { return x&(-x); } int sum(int x) { int sum = 0; while (x>0) { sum += ans[x]; x -= lowbit(x); } return sum; } void add(int x,int d) { while (x<=mmax) { ans[x]+=d; x += lowbit(x); } } int main() { ll n, x,y, left, right; ll mans; while (scanf("%lld%lld%lld", &n,&x,&y)!=EOF) { mans = 0; memset(ans, 0, sizeof(ans)); memset(ans1, 0, sizeof(ans1)); for (int i = 1; i <= n; i++) { scanf("%d",&a[i].date); a[i].num = i; } sort(a + 1, a + n + 1); int index = 1; ans1[a[1].num] = 1; for (int i = 2; i <= n; i++) { if (a[i].date == a[i - 1].date) ans1[a[i].num] = index; else ans1[a[i].num] = ++index; } for (int i = 1; i <= n; i++) { mans+=sum(ans1[i]); add(ans1[i],1); } mans=n*(n-1)/2-mans; cout<<(mans*min(x,y))<<endl; } //system("pause"); return 0; }