hdu 1394 Minimum Inversion Number(線段樹)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1394


題意:給定一個全排列,這道題可以看作求該循環序列的最小逆序數。


思路:

數據範圍只有5000,直接暴力就可以過,187ms。

但是可以用線段樹來優化,46ms可以過。

這道題需要用到一個結論,將一個數移動到序列的最後,逆序數增加(-x+n-1-x)。

具體解釋一下,去掉一個數,假設該數的逆序數爲x,則該序列的逆序數減少x,意味着在該數之後有x個數比他小,

然後把這個數添加到最後面,在該數後面的數有n-1個數中有n-1-x個數比他大,所以序列的逆序數會相應的增加n-1-x.


暴力:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <list>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff                                          //INT_MAX
#define inf 0x3f3f3f3f                                          //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++)                          //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
    if (a>b) {
        if (c>b)
            return b;
        return c;
    }
    if (c>a)
        return a;
    return c;
}
template<class T>
T Maxt(T a, T b, T c) {
    if (a>b) {
        if (c>a)
            return c;
        return a;
    }
    else if (c > b)
        return c;
    return b;
}

const int Maxn=500010;
const int maxn=5005;
int T,n,m;
int a[maxn];

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    while(~sf(n)){
        for1(i,0,n) sf(a[i]);
        int cnt=0,ans=inf;
        for1(i,0,n){
            for1(j,i+1,n){
                if(a[i]>a[j])
                    cnt++;
            }
        }
        if(ans>cnt) ans=cnt;
        for1(i,0,n){
            cnt=cnt-a[i]+n-1-a[i];
            if(ans>cnt)
                ans=cnt;
        }
        pf(ans);
    }
    return 0;
}


線段樹:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <list>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff                                          //INT_MAX
#define inf 0x3f3f3f3f                                          //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++)                          //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
    if (a>b) {
        if (c>b)
            return b;
        return c;
    }
    if (c>a)
        return a;
    return c;
}
template<class T>
T Maxt(T a, T b, T c) {
    if (a>b) {
        if (c>a)
            return c;
        return a;
    }
    else if (c > b)
        return c;
    return b;
}

const int Maxn=500010;
const int maxn=5005;
int T,n,m;
int a[maxn];

struct segTree{
    int l,r;
    int v;
}node[3*maxn];

void pushup(int id){
    node[id].v=node[id<<1].v+node[id<<1|1].v;
}

void build(int id,int l,int r){
    node[id].l=l;
    node[id].r=r;
    node[id].v=0;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
}

void Update(int id,int pos){
    int L=node[id].l,R=node[id].r;
    if(L==R){
        node[id].v++;
        return ;
    }
    int mid=(L+R)>>1;
    if(pos<=mid) Update(id<<1,pos);
    else Update(id<<1|1,pos);
    pushup(id);
}

int Query(int id,int p,int q){
    int L=node[id].l,R=node[id].r;
    if(p<=L&&R<=q) return node[id].v;
    int mid=(L+R)>>1;
    if(q<=mid) return Query(id<<1,p,q);
    if(p>mid) return Query(id<<1|1,p,q);
    return Query(id<<1,p,mid)+Query(id<<1|1,mid+1,q);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    while(~sf(n)){
        build(1,0,n-1);
        int ans=inf,cnt=0;
        for1(i,0,n) {
            sf(a[i]);
            int num=Query(1,a[i]+1,n-1);
            cnt+=num;
            Update(1,a[i]);
        }
        if(ans>cnt) ans=cnt;
        for1(i,0,n){
            cnt=cnt-a[i]+n-1-a[i];
            if(ans>cnt) ans=cnt;
        }
        pf(ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章