1116: 折纸长度
时间限制: 1 Sec 内存限制: 128 MB提交: 41 解决: 20
[提交][状态][讨论版]
题目描述
小s很喜欢折纸。
有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为n个单位长度,并且在每份的边界处分别标上数字0~n。
然后小s开始无聊的折纸,每次他都会选择一个数字,把纸带沿这个数字当前所在的位置翻折(假如已经在边界上了那就相当于什么都不做)。
小s想知道M次翻折之后纸带还有多长。
输入
第一行包含两个正整数N和M,表示纸带的长度和操作的次数。接下来的一行包含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;
}