Minimum Inversion Number hdu 1394

树状数组和线段树都可做

树状数组代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 5000 + 50;
int n;
int a[maxn],c[maxn];

int lowbit(int x) {return x&-x;}

void add(int i, int x)
{
    while(i <= n){
        c[i] += x;
        i += lowbit(i);
    }
}

int query(int i)
{
    int ans = 0;
    while(i){
        ans += c[i];
        i -= lowbit(i);
    }
    return  ans;
}


int main()
{
    //freopen("DATA.c", "r", stdin);
    while(~scanf("%d", &n)){
        int ans = 0;
        memset(c,0,sizeof(c));
        for(int i = 1; i <= n; i ++){
            scanf("%d", &a[i]); ++ a[i];
            ans += query(n) - query(a[i]);
            add(a[i],1);
        }
        int ret = ans;
        for(int i = 1; i <= n; i ++){
            ans += (n-a[i]) - (a[i]-1);
            ret = min(ret, ans);
        }
        printf("%d\n", ret);
    }
    return 0;
}

线段树代码(PS:第一次手写线段树):

#include<bits/stdc++.h>
using namespace std;

const int maxn = 5000 + 50;
int n,a[maxn];

struct Node
{
    int l;
    int r;
    int sum;
    int add;
}segTree[maxn<<2];

void PushDown(int i)
{

    if(segTree[i].add){
        int m = (segTree[i].r - segTree[i].l + 1) >> 1;
        segTree[i<<1].add += segTree[i].add;
        segTree[i<<1|1].add += segTree[i].add;
        segTree[i<<1].sum += segTree[i].add * m;
        segTree[i<<1|1].sum += segTree[i].add * (segTree[i].r - segTree[i].l + 1 - m);
        segTree[i].add = 0;
    }
}

void PushUp(int i)
{
    segTree[i].sum = segTree[i<<1].sum + segTree[i<<1|1].sum;
}


void Build(int i, int l, int r)
{
    segTree[i].l = l;
    segTree[i].r = r;
    segTree[i].sum = 0;
    segTree[i].add = 0;
    if(l == r) return ;
    int mid = l + r >> 1;
    Build(i<<1,l,mid);
    Build(i<<1|1,mid+1,r);
}

void Update(int i, int l, int r, int v)
{
    if(l <= segTree[i].l && segTree[i].r <= r){
        segTree[i].sum += v * (segTree[i].r - segTree[i].l + 1);
        segTree[i].add += v;
        return ;
    }
    PushDown(i);
    int mid = segTree[i].l + segTree[i].r >> 1;
    if(r <= mid){
        Update(i<<1,l,r,v);
    }
    else if(l > mid){
        Update(i<<1|1,l,r,v);
    }
    else{
        Update(i<<1,l,mid,v);
        Update(i<<1|1,mid+1,r,v);
    }
    PushUp(i);
}

int Query(int i, int l, int r)
{
    if(l <= segTree[i].l && segTree[i].r <= r){
        return segTree[i].sum;
    }
    PushDown(i);
    int mid = segTree[i].l + segTree[i].r >> 1;
    int ans = 0;
    if(r <= mid){
        ans += Query(i<<1,l,r);
    }
    else if(l > mid){
        ans += Query(i<<1|1,l,r);
    }
    else{
        ans += Query(i<<1,l,mid);
        ans += Query(i<<1|1,mid+1,r);
    }
    return ans;
}


int main()
{
    //freopen("DATA.c", "r", stdin);
    while(~scanf("%d", &n)){
        int ans = 0;
        Build(1,1,n);
        for(int i = 1; i <= n; i ++){
            scanf("%d", &a[i]); ++a[i];
            ans += Query(1,1,n) - Query(1,1,a[i]);
            Update(1,a[i],a[i],1);
        }
        int ret = ans;
        for(int i = 1; i <= n; i ++){
            ans += (n-a[i])-(a[i]-1);
            ret = min(ret,ans);
        }
        printf("%d\n", ret);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值