HDU_1394_线段树
http://acm.hdu.edu.cn/showproblem.php?pid=1394
线段树入门题,每次读入一个数,就寻找在树中比它大的值的个数,然后更新树,把个数相加就是逆序数,每移动一个数,相当于当前逆序数加上比首元素大的数的数量,减去比首元素小的数的数量。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct segtree { int left,right,sum; }tree[10050]; int n,a[5050]; void build(int pos,int l,int r) { tree[pos].left = l; tree[pos].right = r; tree[pos].sum = 0; if(l < r) { int mid = (l+r)/2; build(pos*2,l,mid); build(pos*2+1,mid+1,r); } } int getsum(int pos,int l,int r) { if(tree[pos].left == l && tree[pos].right == r) return tree[pos].sum; int mid = (tree[pos].left+tree[pos].right)/2; if(r <= mid) return getsum(pos*2,l,r); if(l > mid) return getsum(pos*2+1,l,r); return getsum(pos*2,l,mid)+getsum(pos*2+1,mid+1,r); } void update(int pos,int num) { tree[pos].sum++; if(tree[pos].left == tree[pos].right) return; int mid = (tree[pos].left+tree[pos].right)/2; if(num <= mid) update(pos*2,num); else update(pos*2+1,num); } int main() { while(~scanf("%d",&n)) { int ans = 0; build(1,0,n-1); for(int i = 0;i < n;i++) { scanf("%d",&a[i]); ans += getsum(1,a[i],n-1); update(1,a[i]); } int temp = ans; for(int i = 0;i < n-1;i++) { temp += n-1-a[i]-a[i]; ans = min(temp,ans); } printf("%d\n",ans); } return 0; }