http://acm.hust.edu.cn/vjudge/problem/15764
http://blog.csdn.net/libin56842/article/details/8531117
逆序数的概念:
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。
也是就说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。
而一个排列的逆序树,可以通过这个方法求得:
在输入排列每个数时,找之前比它大的数字有多少个,然后插入线段树,最后加起来的结果就是总的逆序数
对于将最后一个数插到最前面,可以通过循环计算求得
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <cctype> #include <vector> #include <iterator> #include <set> #include <map> #include <sstream> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define pf printf #define sf scanf #define spf sprintf #define pb push_back #define debug printf("! ") #define MAXN 5000 + 5 #define MAX(a,b) a>b?a:b #define blank pf(" ") #define LL long long #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pqueue priority_queue #define INF 0x3f3f3f3f struct node { int l,r,c; }T[MAXN*3]; void PushUp(int rt) { T[rt].c = T[rt<<1].c + T[(rt<<1)+1].c; } void build(int l,int r,int x) { T[x].l = l; T[x].r = r; T[x].c = 0; if (l == r) return; int mid = (l+r)>>1; build(l,mid,x<<1); build(mid+1,r,(x<<1) + 1); } void update(int l,int x) { if(T[x].l == T[x].r && T[x].l == l) { T[x].c++; return; } int mid = (T[x].l + T[x].r)>>1; if (l > mid) { update(l,(x<<1) + 1); } else { update(l,x<<1); } PushUp(x); } int n,m,ans; void query(int l,int r,int x) { if(T[x].l == l && T[x].r == r) { ans += T[x].c; return; } int mid = (T[x].l + T[x].r)>>1; if (l > mid) { query(l,r,(x<<1)+1); } else if(r<=mid) { query(l,r,(x<<1)); } else { query(l,mid,(x<<1)); query(mid+1,r,(x<<1)+1); } } int a[MAXN]; int main() { int t,i,kase=1; while(sf("%d",&n)==1) { build(1,n,1); int sum = 0; for(i=0;i<n;i++) { sf("%d",&a[i]); a[i]++; ans = 0; if(a[i]!=n) query(a[i]+1,n,1); sum+=ans; update(a[i],1); } int result = sum; for(i=n-1;i>=0;i--) { sum = sum - (n - a[i]) + a[i] -1; result = min(result,sum); } pf("%d ",result); } return 0; }