HDU 1394 线段树 求逆序对数

来源:互联网 发布:java 7 64位官方下载 编辑:程序博客网 时间:2024/05/19 00:09

用线段树求逆序数来优化

求x的逆序数只需要访问(x+1,n)段有多少个数

求最小逆序数对所有情况进行爆搜

当把队首x放入数组的后面

此时的逆序数应该为x没放入最后面之前的逆序总数加上(n-x)再减去(x-1)

sum=sum+n-2*a[i]-1;


#include "stdio.h"#include "string.h"#include "math.h"#include "stdlib.h"#include "iostream"#include "algorithm"using namespace std;struct comp{int l,r,mid,x;} data[30001];void build(int l,int r,int k){data[k].l=l;data[k].r=r;data[k].mid=(l+r)/2;data[k].x=0;if (l==r) return ;build(l,data[k].mid,k*2);build(data[k].mid+1,r,k*2+1);}int  query(int l,int r,int k){if (data[k].l==l && data[k].r==r)return data[k].x;if (r<=data[k].mid) return query(l,r,k*2);else if (l>data[k].mid) return query(l,r,k*2+1);else return query(l,data[k].mid,k*2)+query(data[k].mid+1,r,k*2+1);}void update(int x,int k){if (data[k].l==data[k].r){data[k].x++;return ;}if (x<=data[k].mid) update(x,k*2);else update(x,k*2+1);data[k].x=data[k*2].x+data[k*2+1].x;}int main(){int n,sum,ans,i;int a[5010];while (scanf("%d",&n)!=EOF){build(0,n-1,1);sum=0;for (i=1;i<=n;i++){scanf("%d",&a[i]);sum+=query(a[i],n-1,1);update(a[i],1);}ans=sum;for (i=1;i<=n;i++){sum=sum+n-2*a[i]-1;if (sum<ans) ans=sum;}printf("%d\n",ans);}return 0;}