hdu 1394

来源:互联网 发布:双色球走势图软件 编辑:程序博客网 时间:2024/06/05 22:48


题意:给出一个数组是0 ~n-1的排列,然后将第一个数一个一个地加入到数组的最后,使得形成的数组的逆序对最少,输出最少的逆序对;


思路:因为是0~n-1的排列,防止树状数组在0处无法自增,a[i] ++ ,形成1~n的排列。所以第一个数的形成的逆序对的数量是比它小的数的个数即a[1] - 1;比他的的数目为n - a[1],即为到了最后一位所形成的逆序对。所以每把一个数加入到最后,产生的改变是n - a[i] - (a[i] - 1);


#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 10000 + 2;#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x )typedef long long ll;#define eps 10e-10const ll Mod = 1000000007;int n;int a[maxn];int tree[maxn];inline int lowbit(int x){    return x & (-x);}void update(int x,int val){    for(int i = x; i < maxn; i += lowbit(i))    {        tree[i] += val;    }}int get_sum(int x){    int ret = 0;    for(int i = x; i > 0; i -= lowbit(i))        ret += tree[i];    return ret;}int main(){    while( ~ scanf("%d",&n))    {        for(int i = 1; i <= n; i ++)        {            scanf("%d",&a[i]);            a[i] ++;        }        clr(tree,0);        int sum = 0;        for(int i = n; i >= 1; i --)        {            sum += get_sum(a[i]);            update(a[i],1);        }        int ans = sum;        int t = sum;        for(int i = 1; i <= n; i ++)        {            t += n - a[i] - (a[i] - 1);            ans = min(ans,t);        }        cout << ans << endl;    }    return 0;}


0 0
原创粉丝点击