C++-hdu1394-Minimum Inversion Number[数据结构][树状数组]

给出0~n-1的一个排列,可以整体移动,求逆序对最小值

把数字num[i]的加入,等价于树状数组的第n-num[i]位加1

因为num[i]是第 (n-1)-num[i]+1=n-num[i]大的数字,产生逆序对,只可能在其之前已经插入了数字,此时直接区间查询即可

 1 #include <set>
 2 #include <map>
 3 #include <cmath>
 4 #include <queue>
 5 #include <vector>
 6 #include <cstdio>
 7 #include <cstdlib>
 8 #include <cstring>
 9 #include <iostream>
10 #include <algorithm>
11 using namespace std;
12 const int MAXN=5001;
13 int a[MAXN],n,t=1,T;
14 int lb(int i){return i&-i;}
15 void init(){memset(a,0,sizeof(a));}
16 void add(int i,int v){for(;i<=n;a[i]+=v,i+=lb(i));}
17 int sum(int i){int ans=0;for(;i;ans+=a[i],i-=lb(i));return ans;}
18 int query(int i,int j){return sum(j)-sum(i-1);}
19 
20 int num[MAXN],cnt,ans;
21 int main() {
22     while(scanf("%d",&n)!=EOF){
23         init(),cnt=0;
24         for(int i=1;i<=n;i++)scanf("%d",&num[i]);
25         for(int i=1;i<=n;i++)cnt+=query(1,n-num[i]-1),add(n-num[i],1);
26         ans=cnt;
27         for(int i=1;i<n;i++){
28             add(n-num[i],-1);
29             cnt+=query(1,n-num[i]-1)-num[i];
30             add(n-num[i],1);
31             ans=min(ans,cnt);
32         }
33         cout<<ans<<endl;
34     }
35     return 0;
36 }

猜你喜欢

转载自www.cnblogs.com/JasonCow/p/12289625.html