计蒜客 光合作用

du熊是个爱学习的孩子,他总喜欢在生活中做一些小实验,这次du熊想研究一下光合作用。

du熊的实验材料有如下几样:神奇的种子,普通的纸箱和一些光源。一开始du熊将种子均匀的种在了箱子底部,你可以将其看成X轴,种子的位置为X轴上的点。然后du熊用纸板将箱子盖住,并在纸板上安装了一些光源(具体见图)。神奇的种子会在有光的情况下一直向上生长直到没光为止。现在du熊想知道当实验结束时每颗种子的高度是多少?

计蒜客 光合作用_第1张图片

顶上的为光源,光源两边与顶部的夹角都为45°,黄色部分为光照,绿色的为植物。

输入第一行给出一个T,表示测试数据的组数。每组数据的第一行是三个整数n,m,H(1≤n≤100,000, 0≤m≤100,000, 1≤H≤10,000)n表示种子数(编号1-n)m表示光源数,H表示箱子的高度。接下来m行,每行一个整数Xi表示第i个光源在顶部的位置。    

对于每组测试数据,请输出n行,每行一个数表示第i颗种子的最终高度。

样例1

输入:

2

7 1 2

4

4 4 1

1

2

3

4

输出:

0

0

1

2

1

0

0

1

1

1

1

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define abs(a) ((a)>0?(a):(-a))
  4. #define M 100000
  5. int light[M];
  6. int main(){
  7.     int T,n,m,H,i,add,sign,t;
  8.     scanf("%d",&T);
  9.     while(T--){
  10.         scanf("%d%d%d",&n,&m,&H);
  11.         memset(light,0,sizeof(light));
  12.         for(i=0;i<m;i++){
  13.             scanf("%d",&t);
  14.             light[t]=1;
  15.         }
  16.         for(i=1;i<=n;i++){
  17.             add=0;
  18.             sign=1;
  19.             while(light[i+add]==0&&abs(add)<H){
  20.                 if(sign){
  21.                     if(add>=0)add++;
  22.                     else add--;
  23.                     sign=0;
  24.                 }
  25.                 else sign=1;
  26.                 if(i-add>0&&i-add<=n)add=-add;
  27.             }
  28.             add=abs(add);
  29.             printf("%d\n",H-add);
  30.         }
  31.     }
  32.     return 0;
  33. }

 

仔细理解题目,再思考一下,便知道,每颗植物所能成长的最大高度为      H - mins(mins为离它最近光源与它的距离)。故只要能找到离第i颗植物最近的光源即可,怎么找呢?

我使用的是左右探测法(自己脑补出来的名字。。),灵感来自解决散列冲突的平方探测法,对于植物 i 我们先观察他左边 距离为1 的位置,再观察右边距离为1 的位置

如果不存在光源,再找左边距离为 2 的位置 ,依次类推,直至距离大于等于H或找到光源,若找到,则当前植物的高度即可输出,否则 植物高度为0;

惯例吐槽(之所以老在计蒜客做题有两个原因,第一,简单。。。。。(毕竟我新手),第二,有将题目合理分类,使我可针对性的练习,但是,这道题虽然被分类在二分查找,但我完全看不出哪里需要二分的说,应该是存在二分查找的解法,但我没想到,以后想到了再重新写吧(并不会),嗯,这题麻烦的地方就是左右寻找可能的越界,其他都没什么了,

如果不是这两天刚好AC了,我都觉得没必要写。。)

你可能感兴趣的:(计蒜客 光合作用)