折纸长度

来源:互联网 发布:精灵王座网络上映 编辑:程序博客网 时间:2024/05/16 02:07

1116: 折纸长度

时间限制: 1 Sec  内存限制: 128 MB
提交: 41  解决: 20
[提交][状态][讨论版]

题目描述

    小s很喜欢折纸。

       有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为n个单位长度,并且在每份的边界处分别标上数字0~n。

       然后小s开始无聊的折纸,每次他都会选择一个数字,把纸带沿这个数字当前所在的位置翻折(假如已经在边界上了那就相当于什么都不做)。

       小s想知道M次翻折之后纸带还有多长。

输入

第一行包含两个正整数NM,表示纸带的长度和操作的次数。接下来的一行包含M个整数Di,其中Di表示第i次选择的数字。

输出

只有一个数字,即纸带最后的长度。

样例输入

5 23 5

样例输出

2

提示

【数据规模和约定】

60%的数据中N<=3000,M<=3000;

100%的数据中N<=10^18,M<=3000.

来源

想法


看到数据范围确实下来一跳(本来打算模拟。。)

我们可以用L,R表示纸片的左右区间,长度即为R-L

其实当我们枚举到第i此翻折的点时,可以通过o(n)的时间把这个点此时的坐标值算出,更新

要注意了L,R经过翻折后改变坐标,L是有可能大于R的

还有就是要规定翻折的方向(我是向左的)

别的至于翻折后的值怎么求就不说了。。

<pre name="code" class="cpp">#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>using namespace std;int m,i,j;long long n,x,l,r,a[3005];int main(){    cin>>n>>m;    for(i=1;i<=m;i++)        scanf("%lld",&a[i]);    l=0;r=n;    for(i=1;i<=m;i++)    {        x=a[i];        for(j=1;j<i;j++)            if(a[j]<x) x=a[j]*2-x;        a[i]=x;        l=min(l,x*2-r);        r=x;        if(l>r) swap(l,r);    }    cout<<r-l;    return 0;}




0 0