POJ2182(Lost Cows)

最近在写遗传算法求TSP时看到了grefenstette编码,于是想起了这个题目,这题我原来是用线段树写的C语言提交的,用时157ms,刚用树状数组+二分写用C++提交只跑了47ms,感觉快了不少。

这题数学模型是:现有一个1到n的一个被打乱的排列,告诉你每个数的左边有多少个数比它小,显然第一个数左边没有比它小的数,求每个位置上的数。

grefenstette编码差不多,只是把左边改成了右边再加1,例如:8 6 7 5 3 4 1 2编码后是:8 6 6 5 3 3 1 1

View Code
 1 #include <stdio.h>

 2 #include <string.h>

 3 #define N 8010

 4 int a[N],c[N],f[N],n;

 5 void update(int k)

 6 {

 7   for(;k<=n;k+=(k&(-k))) f[k]++;

 8 }

 9 int getsum(int k)

10 {

11   int sum=0;

12   for(;k>0;k-=(k&(-k)))  sum+=f[k];

13   return sum;

14 }

15 int bs(int k)

16 {

17   int min=0,max=n,mid;

18   while(min+1!=max)

19   {

20     mid=(min+max)>>1;

21     if(mid-1-getsum(mid)<a[k])  min=mid;

22     else  max=mid;

23   }

24   return max;

25 }

26 int main()

27 {

28   while(~scanf("%d",&n))

29   {

30     a[1]=0;

31     for(int i=2;i<=n;i++) scanf("%d",&a[i]);

32     memset(f,0,sizeof(f));

33     for(int i=n;i>0;i--)

34     {

35       c[i]=bs(i);

36       update(c[i]);

37     }

38     for(int i=1;i<=n;i++) printf("%d\n",c[i]);

39   }

40   return 0;

41 }

这题太经典了,又用线段树(堆实现的)写了一遍,时间还是47ms。感觉这个思路更清晰,更巧妙。 

View Code
#include <stdio.h>

#define N 8002

int n,D;

int x[N],id[N];

int sum[4*N];

void init()

{

  int i;

  for(D=1;D<n+2;D<<=1);

  for(i=1;i<=n;i++) sum[i+D]=1;

  for(i=D-1;i;i--)  sum[i]=sum[i<<1]+sum[i<<1|1];

}

void update(int k)

{

  k+=D;

  sum[k]=0;

  for(;k^1;k>>=1) sum[k>>1]=sum[k]+sum[k^1];

}

int query(int k)

{

  int i;

  for(i=1;i<D;)

  {

    if(sum[i<<1]>=k)  i<<=1;

    else  k-=sum[i<<1],i=i<<1|1;

  }

  return i-D;

}

int main()

{

  int i;

  while(~scanf("%d",&n))

  {

    x[1]=0;

    for(i=2;i<=n;i++) scanf("%d",&x[i]);

    init();

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

    {

      id[i]=query(x[i]+1);

      update(id[i]);

    }

    for(i=1;i<=n;i++) printf("%d\n",id[i]);

  }

  return 0;

}

 

你可能感兴趣的:(poj)