HDU1394最小逆序数

来源:互联网 发布:淘宝万斯正品店 编辑:程序博客网 时间:2024/04/28 00:56

层层优化,请往下看(按照编程复杂度排名)

1.暴力 250ms

#include<stdio.h>int a[5003];int main(){    int n, i, j, sum;    while (scanf("%d", &n) != EOF)    {        sum = 0;        for (i = 1; i <= n; i++)        {            scanf("%d", a + i);            for (j = 1; j < i; j++)                if (a[j] > a[i])                    sum++;        }        int ans = sum;        for (i = 1; i <= n; i++)        {            sum += (-a[i] + n - a[i] - 1);            //公式:第一个数移到最后位置后逆序数            //sum=sum+(-low[a[i]]+up[a[i]])            //在0-(n-1)序列里low[a[i]]=a[i],up[a[i]]=n-a[i]+1;            if (sum < ans)                ans = sum;        } printf("%d\n", ans);    }}

2、记忆优化 62ms

#include<stdio.h>int a[5003];int main(){   //freopen("//home//amb//桌面//1.in","r",stdin);    int n, i, j, sum;    while (scanf("%d", &n) != EOF)    {        sum = 0;        bool chu[5003]={0};//已经出来的记录一下        for(i=0;i<=n;i++)        {            chu[i]=1;        }        for (i = 1; i <= n; i++)        {            scanf("%d", &a[i]);            chu[a[i]]=0;            for(j=0;j<a[i];j++)                sum+=chu[j];        }      //  printf("%d\n", sum);        int ans = sum;        for (i = 1; i <= n; i++)        {            sum += (-a[i] + n - a[i] - 1);            //公式:第一个数移到最后位置后逆序数            //sum=sum+(-low[a[i]]+up[a[i]])            //在0-(n-1)序列里low[a[i]]=a[i],up[a[i]]=n-a[i]+1;            if (sum < ans)                ans = sum;        } printf("%d\n", ans);    }}
3、树状数组优化31ms

#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <bitset>using namespace std ;#define zero {0}#define INF 2000000000#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}int a[5003];int chu[5003] = {0};int n;int lowbit(int x){    return (x & (-x));}void add(int i, int num){    while (i <= n)    {        chu[i] += num;        i += lowbit(i);    }}int Sum(int x){    int sum = 0;    while (x > 0)    {        sum += chu[x];        x -= lowbit(x);    }    return sum;}int main(){    // freopen("//home//amb//桌面//1.in", "r", stdin);    while (scanf("%d", &n) + 1)    {        memset(chu, 0, sizeof(chu));        int sum = 0;        for (int i = 1; i <= n; i++)        {            add(i, 1);        }        int k;        for (int i = 1; i <= n; i++)        {            scanf("%d", &a[i]);            add(a[i]+1, -1);            sum += Sum(a[i]+1);        }      //  printf("%d\n", sum);        int ans = sum;        for (int i = 1; i <= n; i++)        {            sum += (-a[i] + n - a[i] - 1);            //公式:第一个数移到最后位置后逆序数            //sum=sum+(-low[a[i]]+up[a[i]])            //在0-(n-1)序列里low[a[i]]=a[i],up[a[i]]=n-a[i]+1;            if (sum < ans)                ans = sum;        }        printf("%d\n", ans);    }}

4、线段树优化 46ms

                                 #define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <bitset>using namespace std ;#define zero {0}#define INF 2000000000#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){return fabs(x) < EPS ? 0 :(x < 0 ? -1 : 1);}#define LL(x) ((x)<<1) #define RR(x) ((x)<<1|1) //twice+1struct Seg_Tree{    int left,right,val;    int calmid()    {        return (left+right)/2;    }}tt[15000];int val[5001];void build(int left,int right,int idx){    tt[idx].left=left;    tt[idx].right=right;    tt[idx].val=0;    if(left==right)        return ;    int mid=tt[idx].calmid();    build(left,mid,LL(idx));    build(mid+1,right,RR(idx));}int query(int left,int right,int idx){    if(left==tt[idx].left&&right==tt[idx].right)        return tt[idx].val;    int mid=tt[idx].calmid();    if(right<=mid)    {        return query(left,right,LL(idx));    }    else if(mid<left)    {        return query(left,right,RR(idx));    }    else    {        return query(left,mid,LL(idx))+query(mid+1,right,RR(idx));    }}void update(int id,int idx){    tt[idx].val++;    if(tt[idx].left==tt[idx].right)        return ;    int mid=tt[idx].calmid();    if(id<=mid)    {        update(id,LL(idx));    }    else    {        update(id,RR(idx));    }}int main(){        #ifdef DeBUGs        freopen("//home//amb//桌面//1.in","r",stdin);    #endif    int n;    while(scanf("%d",&n)+1)    {        build(0,n-1,1);        int sum=0;        for(int i=0;i<n;i++)        {            scanf("%d",&val[i]);            sum+=query(val[i],n-1,1);            update(val[i],1);        }        int ret=sum;        for(int i=0;i<n;i++)        {            sum=sum-val[i]+(n-val[i]-1);            ret=min(ret,sum);        }        printf("%d\n", ret);    }            return 0;}



5、优化得好一些的线段树 31ms

#include <iostream>#include <cstdio>#include <cstdlib>#define M 5010using namespace std;int n, map[M], minn, tmp, ans;struct TREE{    int l, r, sum; //区间内已插入的节点数} T[M << 2];void create(int u, int l, int r){    T[u].l = l; T[u].r = r;    if (T[u].l == T[u].r)    {        T[u].sum = 0;        return;    }    int mid = (T[u].l + T[u].r) >> 1;    create(u << 1, l, mid);    create(u << 1 | 1, mid + 1, r);    T[u].sum = T[u << 1].sum + T[u << 1 | 1].sum;}void query(int u, int l, int r){    if (T[u].l >= l && T[u].r <= r)    {        tmp += T[u].sum;        return;    }    int mid = (T[u].l + T[u].r) >> 1;    if (r <= mid) query(u << 1, l, r);    else if (l >= mid + 1) query(u << 1 | 1, l, r);    else    {        query(u << 1, l, mid);        query(u << 1 | 1, mid + 1, r);    }}void updata(int u, int pos){    if (T[u].l == T[u].r)    {        T[u].sum++;        return;    }    int mid = (T[u].l + T[u].r) >> 1;    if (pos <= mid) updata(u << 1, pos);    else updata(u << 1 | 1, pos);    T[u].sum = T[u << 1].sum + T[u << 1 | 1].sum;}int main(){    while (scanf("%d", &n) != EOF)    {        minn = 0;        for (int i = 1; i <= n; i++)        {            scanf("%d", &map[i]);            map[i]++;//避免0的出现        }        create(1, 1, n);        for (int i = 1; i <= n; i++)        {            tmp = 0;            if (map[i] + 1 <= n) query(1, map[i] + 1, n);            minn += tmp;            updata(1, map[i]);        }        ans = 9999999;        for (int i = 1; i <= n; i++)        {            minn = minn - (map[i] - 1) + n - 1 - (map[i] - 1);            //我们曾经把所有的数字都加过1,所以要减去            ans = min(ans, minn);        }        printf("%d\n", ans);    }    return 0;}


0 0