折纸

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;
}
原文地址:https://www.cnblogs.com/aziint/p/8465980.html