题目的意思一开始没有看清楚,题目的意思是:

       给你一段序列a1,a2,a3,a4,a5,a6,a7,,然后这段序列可以一直调动第一个数字到最后,例如:

a2,a3,a4,a5,a6,a7,a1,…………直到循环了一遍。然后从这么多的序列中求出逆序列最小的一组。注意,序列中的数是从0开始计数的。一开始做还以为给的数字是随意给的呢,笑话,晕了好久。哈哈,切入正题,这道题还是树状数组,但是这道题有了别样的技巧,对于我这种小菜,算是吧。(大牛们做这个可能跟喝白开水一样,所以算不上技巧)。

      一开始,挺笨的,直接列举全部序列,然后就一段一段用树状数组求出各自的逆序列,哎,序列给的可是5000啊,列举全部,就是5000个不同的序列,然后每个再求其逆序列,肯定TLE啊。

     OK,说说收获吧,原来不用保存全部的序列,是有数学规律的,我一开始想不到,当然跟我没有理解好题意有很大关系。记住,上面说过序列里面的数是从0开始计数的,比如序列可能为0,4,2,1,6,3,5,然后它的逆序列为多少呢?小学生都会数啊,呵呵,当然是sum=0+0+1+2+0+2+1=6啦,那么另一个序列5,0,4,2,1,6,3,是多少?

     想想,5换到最前去了(为什么不将5从前往后换呢?因为从后面往前换,好算一点),接下来注意,,那么原来比5大的个数1,此刻就

要用sum-1;因为5掉到最前,那么原来比5大的数,原来是逆序,现在恰好它变为正序了。那么原来比5小的个数5就变为逆序了,那么

(sum-1)+5,,算算看对不对。此刻sum2=sum-1+5=6-1+5=10;

刚刚好序列2的sum2=0+1+1+2+3+0+3=10;哈哈,数学真伟大。

#include<iostream>
#define lowbit(x) x&(-x)
#define M 5001
using namespace std;

int flag[5001];
int add(int n)
{
    while(n<=M)
    {
        flag[n]++;
        n+=lowbit(n);
    }
    return 0;
}

int subsum(int n)
{
    int sum=0;
    while(n>0)
    {
        sum+=flag[n];
        n-=lowbit(n);
    }
    return sum;
}

int main(void)
{
    int number[5001],n;
    while(cin>>n)
    {
        int count=1,k=0,h=1,i,min=2100000000,sum,lmin,lmax;
        for( i=1;i<=n;i++)
            scanf("%d",&number[i]);
            sum=0;
            memset(flag,0,sizeof(flag));
            for(i=1;i<=n;i++)
            {       
                //cout<<lmin<<endl;
                lmax=i-1-subsum(number[i]+1);
                add(number[i]+1);
                sum+=lmax;
                //cout<<lmax[i]<<"   "<<lmin[i]<<endl;
            }
        //    cout<<sum<<endl;
            for(i=n;i>1;i--)
            {                                    //注意在这道题中,每个number[i]都加上了1,因为树状数组处理的时候,不能处理0
                sum+=number[i]-(n-(number[i]+1));//很神奇,找出规律,就是比number[i]+1大的数,前面比他大的个数为n-(number[i]+1),
                                                    //那么比它小的,当然就是number[i]+1-1啦,呵呵,又数数学规律
        //        cout<<sum<<endl;
                if(min>sum)
                    min=sum;
            }
        //    cout<<sum<<endl;
       
            //cout<<max<<endl;
        cout<<min<<endl;
    }
    return 0;
}

 

改的很乱,哈哈,见谅!

posted on 2011-04-23 21:11  cchun  阅读(521)  评论(0编辑  收藏  举报