尺取法其实是一种很简单的算法,思想原来也用过,但一直不知道。。这两天恰好做了两道有关尺取法的题,就来总结一下。

  首先,什么是尺取法?尺取法通常是指对数组保存一对下标(起点、重点),然后根据实际情况交替推进两个端点直到得出答案的方法,因为这种方法像尺取虫的爬行方式所以得名。其实就是求在一个线性的数组上求关于区间的问题。由于只对区间的两个端点进行改变,所以中间部分就不需要进行维护更新了,只要维护两端即可。可以大大降低复杂度。

  例题一:poj3061 给定长度为n的整数数列以及整数S,求出总和不小于S的连续子序列的长度的最小值,如果解不存在,输出0。

  解法一:(1)s=t=sum=0初始化

      (2)只要sum<S,就不断将sum增加a(t),并将t增加1

      (3)如果(2)中无法满足sum>=S则终止,否则将ans更新为min(ans,t-s)。

      (4)将sum将sum减去a(s),s增加1后回到(2)

      这其实就是一个典型的尺取法,我们当得到sum>=S时再减去a(s)它又会小于S就相当于重新确定了起点,同样的,也就同时确定了终点,并且因为新区间和原来的区间有很大一部分重合,所以直接对sum进行加减就可以了,无需重新计算。

  例题二:给出一串珠子,有2n个,其中有黑色和白色珠子各n个,黑色逆时针编号,白色顺时针编号,白色黑色随机排列,要找一段长度为n的区间,要求区间内珠子的编号为1-n(不一定从小到大或从大到小出现,只要1-n都出现即可)。(感谢畅神出题!)数据范围1000万。

  解法二:由于数据范围很大,所以必须用O(n)的方法解。我们先把珠子编好号,然后找一个作为起点,向后找n个珠子,记录下每种编号的珠子各有几个和一共出现了几个编号的珠子。然后,我们将头上的珠子取出,加上第n+1个珠子,重复该过程,直到出现了n个编号的珠子我们就找到了一个合法区间。这也是尺取法的一种,中间n-2个珠子我们是不需要管的,只要取出和加上头和尾的珠子就行了。这样只要枚举n个起点就可以轻松找出这个区间。

  总结:总的来说尺取法的思想很好理解,代码难度不算高,在noip中考很合适,有些题可以方便的解决,个人感觉应该掌握。

posted on 2016-09-07 23:06  appgle  阅读(1637)  评论(0编辑  收藏  举报