• 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;
    }
  • 相关阅读:
    本地时间与UTC(世界协调时间)的转换
    windows共享在linux下挂载
    日期中带的 T 是什么意思
    FCBU喜马拉雅音频批量下载器
    C#使用[CefSharp]Chrome浏览器(1)安装
    云锵投资 2022 年 2 月简报
    云锵投资 2022 年 1 月简报
    MySQL分组(group by)取最大值、最小值
    tabel布局中给tr加border边框
    ant 使用指南
  • 原文地址:https://www.cnblogs.com/algorithms/p/2512002.html
Copyright © 2020-2023  润新知