poj 2182 树状数组

这题对于O(n^2)的算法有很多,我这随便贴一个烂的,跑了375ms。

#include<iostream>

#include<algorithm>

using namespace std;

int mat[8008];

int main()

{

    int i,j,t,n;

    scanf("%d",&n);

    

         mat[0]=1;

         for(i=1;i<n;i++) 

         {

             scanf("%d",&t);

             mat[i]=t+1;                    

             for(j=0;j<i;j++)                       

               if(mat[j]>=mat[i])

                {  mat[j]++;}

         }

         for(i=0;i<n;i++)

            printf("%d\n",mat[i]);

    

    return 0;

}    
View Code


还是来看树状数组的解法。我们从后面往见面看,假设第i个牛前面有Rank[i]个牛标号比他小,由此很容易得出最后一个牛的编号一定是Rank[n]+1。我们将最后一个牛去掉后,剩下n-1牛时,对于第n-1个牛的道理是一样的,只不过不同的是Rank[n-1]+1之前有多少个牛已经不存在了,即已经确定位置。我们就用树状数组保存被去掉的牛个数,C[i]表示标号i之前已经有多少个牛确定位置。那么我们每次就是要找某个数k,使得k-C[k]==Rank[i]+1。这就是第i个牛的确定位置。

#include<iostream>

#include<cstring>

#include<cstdio>

#include<algorithm>

#include<cmath>

#define Maxn 8010

#define inf 0x7fffffff

#define lowbit(x) (x&(-x))

using namespace std;



int C[Maxn],n,Rank[Maxn],ans[Maxn];

void init()

{

    memset(C,0,sizeof(C));

}

int Sum(int pos)

{

    int sum=0;

    while(pos>0)

    {

        sum+=C[pos];

        pos-=lowbit(pos);

    }

    return sum;

}

void update(int pos,int num)

{

    while(pos<=n)

    {

        C[pos]+=num;

        pos+=lowbit(pos);

    }

}

int getPos(int i)

{

    int l=1,r=n,temp;

    while(l<r)

    {

        int mid=(l+r)>>1;

        temp=mid-Sum(mid);

        if(temp<i)

            l=mid+1;

        else

            r=mid;

    }

    return l;

}

int main()

{

    int i,j,a,b,c;

    while(scanf("%d",&n)!=EOF)

    {

        init();

        for(i=2;i<=n;i++)

            scanf("%d",&Rank[i]);

        Rank[1]=0;

        for(i=n;i>=1;i--)

        {

            int pos=getPos(Rank[i]+1);

            ans[i]=pos;

            update(pos,1);

        }

        for(i=1;i<=n;i++)

            printf("%d\n",ans[i]);

    }

    return 0;

}

 

你可能感兴趣的:(树状数组)