尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以说尺取法是一种高效的枚举区间的方法,是一种技巧,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案,所以要先判断是否可以使用尺取法再进行计算。

使用尺取法时应清楚以下四点:

1、 什么情况下能使用尺取法?

2、何时推进区间的端点?

3、如何推进区间的端点?

4、何时结束区间的枚举?

尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步得到根据其端点得到,那么尺取法便是不可行的。首先,明确题目所需要求解的量之后,区间左右端点一般从最整个数组的起点开始,之后判断区间是否符合条件在根据实际情况变化区间的端点求解答案。

其实,这种方法很类似于蚯蚓的蠕动。

1)用一对脚标i, j。最开始都指向第一个元素。

2)如果区间i到j之和比s小,就让j往后挪一位,并把sum的值加上这个新元素。相当于蚯蚓的头向前伸了一下。

3)如果区间i到j之和比s大,就让sum减掉第一个元素。相当于蚯蚓的尾巴向前缩了一下。

4)如果i到j之和刚好等于s,则输入。

using namespace std;
int dist[1000005];
int n, sum, ans = 0, tmp, st, mid;

int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
        scanf("%d", &dist[i]);
        sum += dist[i];
    }
    mid = sum / 2;
    int j = 0;
    for(int i = 0; i < n; i++){
        while(tmp < mid){
            tmp += dist[(j++) % n];
        }
        ans = max(ans, min(sum - tmp, tmp));
        //注意要取min(sum - tmp, tmp),由于计算机的运算性质,sum/2向下取整
        //因此无法比较事实上sum - tmp比tmp小
        tmp -= dist[i];
    }
    printf("%d", ans);
    return 0;
}