10 1 3 6 9 0 8 5 7 4 2
16
线段树,第一遍初始化的时候计算出逆序对,然后之后每次把第一个数移动到最后一个位置的时候需要把比他小的那部分数都减一,然后这个数的值就应该是比他大的数的个数,因为,移到最后一个位置上了所有数都在他前面。。。。
代码
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef struct { int l,r,val,lazy,show; }Tree; Tree tree[50000]; int a[5005]; void Push(int t) { tree[2*t+1].val+=(tree[2*t+1].r-tree[2*t+1].l+1)*tree[t].lazy; tree[2*t+2].val+=(tree[2*t+2].r-tree[2*t+2].l+1)*tree[t].lazy; tree[2*t+1].lazy+=tree[t].lazy; tree[2*t+2].lazy+=tree[t].lazy; tree[t].lazy=0; } void Build(int t,int l,int r) { tree[t].l=l; tree[t].r=r; tree[t].val=0; tree[t].lazy=0; tree[t].show=0; if (l==r) return; int mid=(l+r)>>1; Build(2*t+1,l,mid); Build(2*t+2,mid+1,r); } void point_update(int t,int x,int val) { if (tree[t].l==tree[t].r) { tree[t].val=val; tree[t].show=1; return; } if (tree[t].lazy!=0) { Push(t); } int mid=(tree[t].l+tree[t].r)>>1; if (x<=mid) point_update(2*t+1,x,val); else point_update(2*t+2,x,val); tree[t].val=tree[2*t+1].val+tree[2*t+2].val; tree[t].show=tree[2*t+1].show+tree[2*t+2].show; } void line_update(int t,int l,int r,int val) { if (l>r) return; if (tree[t].l==l && tree[t].r==r) { tree[t].val+=(tree[t].r-tree[t].l+1)*val; tree[t].lazy+=val; return; } if (tree[t].lazy!=0) { Push(t); } int mid=(tree[t].l+tree[t].r)>>1; if (l<=mid) line_update(2*t+1,l,min(mid,r),val); if (r>mid) line_update(2*t+2,max(l,mid+1),r,val); tree[t].val=tree[2*t+1].val+tree[2*t+2].val; } int query_show(int t,int l,int r) { if (tree[t].l==l && tree[t].r==r) { return tree[t].show; } int mid=(tree[t].l+tree[t].r)>>1; int ret=0; if (l<=mid) ret+=query_show(2*t+1,l,min(mid,r)); if (mid<r) ret+=query_show(2*t+2,max(mid+1,l),r); return ret; } int main() { int i,j,n,ans; while(scanf("%d",&n)!=EOF) { Build(0,0,n-1); for (i=0;i<n;i++) { scanf("%d",&a[i]); point_update(0,a[i],query_show(0,a[i],n-1)); } ans=tree[0].val; for (i=0;i<n;i++) { point_update(0,a[i],n-a[i]-1); line_update(0,0,a[i]-1,-1); ans=min(ans,tree[0].val); } printf("%d\n",ans); } return 0; }