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