HDU 1394 Minimum Inversion Number(线段树|找规律)

昨天看了杭电大神的博客,受益颇多啊!一下子觉得代码风格很重要,自己的果然太繁琐了!好好的学习了一下什么叫飘逸的风格,顺便附上大神的博客地址,可以专门学习线段树。

地址:http://www.notonlysuccess.com/index.php/segment-tree-complete/

里面线段树的学习很具体。

这题就是找规律先算出原数组的最小逆序数,用线段树求,之后是一个规律sum+=n-s[i]*2+1   

看看代码:

#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn=5555;
int sum[maxn<<2];
void pushup(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
	sum[rt]=0;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
}
void update(int p,int l,int r,int rt)
{
	if(l==r)
	{
		sum[rt]++;
		return ;
	}
	int mid=(l+r)>>1;
	if(p<=mid) update(p,lson);
	else update(p,rson);
	pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R)
		return sum[rt];
	int mid=(l+r)>>1;
	int ret=0;
	if(L<=mid) ret+=query(L,R,lson);
	if(R>mid) ret+=query(L,R,rson);
	return ret;
}
int x[maxn];
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		build(0,n-1,1);
		int sum=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&x[i]);
			sum+=query(x[i],n-1,0,n-1,1);
			update(x[i],0,n-1,1);
		}
		int ret=sum;
		for(int i=0;i<n;i++)
		{
                 sum+=n-x[i]-x[i]-1;
				 ret=min(ret,sum);
		}
		printf("%d\n",ret);
	}
	return 0;
}

 其实min也是内置的函数,int i重定义之类的编译过不去,其实交了也可以过的。

 

 

posted @ 2012-02-05 11:55  Lxsec  阅读(363)  评论(0编辑  收藏  举报