Description
小 (s) 很 喜欢折纸。
有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为 (n) 个单位长度,并且在每份的边界处分别标上数字 (0) ~ (n) 。
然后小 (s) 开始无聊的折纸,每次他都会选择一个数字,把纸带沿这个数字当前所在的位置翻折(假如已经在边界上了那就相当于什么都不做)。
小 (s) 想知道 (M) 次翻折之后纸带还有多长。
Input
输入文件fold.in的第一行包含两个正整数 (N) 和 (M) ,表示纸带的长度和操作的次数。接下来的一行包含 (M) 个整数 (D_i) ,其中 (D_i) 表示第 (i) 次选择的数字。
Output
输出文件为 (fold.out) 。输出文件只有一个数字,即纸带最后的长度。
Sample
Sample Input
5 2
3 5
Sample Output
2
Limit
$60% $ 的数据中 (N le 3000,Mle 3000) ;
(100\%) 的数据中 (Nle 10^{18},Mle3000) 。
Solution
每次翻折的时候就计算一下翻折点现在的坐标值。
#include<bits/stdc++.h>
using namespace std;
#define M 3001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define ll long long
inline ll read() {
ll x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
ll n, l, r, a[M];
int m;
int main() {
freopen("fold.in", "r", stdin); freopen("fold.out", "w", stdout);
r = n = read(); m = read();
rep(i, 1, m) {
ll x = a[i] = read(); rep(j, 1, i - 1) if(a[j] < x) x = (a[j] << 1) - x; a[i] = x;
l = min(l, (x << 1) - r); r = x; if(l > r) swap(l, r);
}
printf("%I64d", r - l);
return 0;
}