HDU-1394 求逆序对数

来源:互联网 发布:梅花谱棋谱软件 编辑:程序博客网 时间:2024/05/05 19:16

参考题解之后,AC!

算是NOIP2011后的线段树第一题!

逆序对数——经典问题吧。

逆序对数有一个性质,见DISCUSS。

统计某一个区间的元素个数,当然线段树!

/* * hdu-1394 minimum inversion number * mike-w * 2011-11-25 * --------------------------------- * reckon with this:  * contains a permutation of the n integers from 0 to n-1. * tip: * 线段树坐标的范围不一定从1开始,可以从0开始——学习了! */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>#define MAX_N 5050#define TREE_SIZE (4*MAX_N)typedef struct x_snode{int l,r,num;}snode;snode tree[TREE_SIZE];int a[MAX_N];int N;int build(int root,int l,int r){tree[root].l=l;tree[root].r=r;tree[root].num=0;if(l==r) return 0;int mid=(l+r)/2;build(2*root,l,mid);build(2*root+1,mid+1,r);return 0;}int insert(int root,int x){tree[root].num++;if(tree[root].l==tree[root].r)return 0;int mid=(tree[root].l+tree[root].r)/2;if(x<=mid)insert(root*2,x);elseinsert(root*2+1,x);return 0;}int search(int root,int l,int r){if(l>r)/* do NOT omit this case */return 0;if(l==tree[root].l && tree[root].r==r)return tree[root].num;int mid=(tree[root].l+tree[root].r)/2;if(r<=mid)return search(root*2,l,r);else if(l>mid)return search(root*2+1,l,r);elsereturn search(root*2,l,mid) + search(root*2+1,mid+1,r);}int main(void){#ifndef ONLINE_JUDGEassert(freopen("in","r",stdin));#endifint i,tmp,total,ans;while(scanf("%d",&N)!=EOF){for(i=1;i<=N;i++)scanf("%d",a+i);total=0;build(1,0,N-1);for(i=1;i<=N;i++){total+=search(1,a[i]+1,N-1);insert(1,a[i]);}ans=total;for(i=1;i<=N;i++){total+=N-2*a[i]-1;if(total<ans)ans=total;}printf("%d\n",ans);}return 0;}


原创粉丝点击