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重定义之类的编译过不去,其实交了也可以过的。
浙公网安备 33010602011771号