题目
解题思路
设dp[i]表示前一列取到从下往上数第i个格子方案数。
我们发现dp数组是个二值函数。即当
1
<
=
i
<
=
i
d
1<=i<=id
1<=i<=id时,
d
p
[
i
]
=
x
dp[i]=x
dp[i]=x,当
i
d
+
1
<
=
i
<
=
h
[
i
−
1
]
id+1<=i<=h[i - 1]
id+1<=i<=h[i−1]时,
d
p
[
i
]
=
1
dp[i]=1
dp[i]=1。
记录这个二值点,及其权值,转移即可。
复杂度O(n)。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
void read(int &x) {
x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
}
const int N = 1e6 + 100;
const int MOD = 1e9 + 7;
int n;
int sa[N];
int main() {
//freopen("0.txt", "r", stdin);
read(n);
for (int i = 1; i <= n; i++) read(sa[i]);
ll ans = 0, id = 1, res = 0; sa[0] = 1;
for (int i = 1; i <= n; i++) {
if (sa[i] >= sa[i - 1]) {
res = (res * (id - 1) + sa[i - 1] - 1) % MOD;
id = sa[i - 1];
ans = (ans + sa[i] - 1 + res * (sa[i - 1] - 1)) % MOD;
}
else if (sa[i] > id) {
res = (res * (id - 1) + sa[i] - 1) % MOD;
id = sa[i];
ans = (ans + sa[i] - 1 + res * (sa[i] - 1)) % MOD;
}
else {
res = (res * (sa[i] - 1) + sa[i] - 1) % MOD;
id = sa[i];
ans = (ans + sa[i] - 1 + res * (sa[i] - 1)) % MOD;
}
}
printf("%lld\n", ans);
return 0;
}