/*
Problem: Count Ways to Replace Missing Values and Make Adjacent Differences Valid
Company Tag: UI
Problem Statement:
We are given an array arr.
Some values are missing and are represented by 0.
Every missing value can be replaced with a non-negative integer.
The final array is good if:
abs(arr[i] - arr[i - 1]) <= 1
for every adjacent pair.
Return the number of valid arrays modulo 1e9 + 7.
Constraints:
1 <= n <= 500
0 <= arr[i] <= 10^9
At least one element in arr is non-zero.
Missing values are represented by 0.
Simple Brute Force:
Try every possible value for every zero.
Why Brute Force Fails:
Values can be very large, and there can be many zeros.
Better Idea:
At least one value is fixed.
Between two fixed values, the zero segment behaves like a walk:
from left fixed value to right fixed value,
where each step can change by -1, 0, or +1.
Since n <= 500, the number of reachable values around a fixed value
is small enough for map-based DP.
Dry Run:
arr = [2, 0, 3]
The missing value must be close to both 2 and 3.
Valid arrays:
[2, 2, 3]
[2, 3, 3]
Answer = 2
Time Complexity:
O(n^2)
Space Complexity:
O(n)
*/
#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007LL;
long long countFreeSide(long long fixedValue, int steps) {
/*
This handles zeros before the first fixed value
or after the last fixed value.
We start from the fixed value and move step by step.
*/
unordered_map<long long, long long> dp;
dp[fixedValue] = 1;
for (int step = 0; step < steps; step++) {
unordered_map<long long, long long> nextDp;
for (auto item : dp) {
long long value = item.first;
long long ways = item.second;
for (long long nextValue = value - 1; nextValue <= value + 1; nextValue++) {
if (nextValue >= 0) {
nextDp[nextValue] += ways;
nextDp[nextValue] %= MOD;
}
}
}
dp = nextDp;
}
long long totalWays = 0;
for (auto item : dp) {
totalWays = (totalWays + item.second) % MOD;
}
return totalWays;
}
long long countBetweenFixedValues(long long leftValue, long long rightValue, int zeroCount) {
/*
This counts the ways to fill zeroCount values between:
leftValue ... rightValue
*/
unordered_map<long long, long long> dp;
dp[leftValue] = 1;
for (int step = 0; step < zeroCount; step++) {
unordered_map<long long, long long> nextDp;
for (auto item : dp) {
long long value = item.first;
long long ways = item.second;
for (long long nextValue = value - 1; nextValue <= value + 1; nextValue++) {
if (nextValue >= 0) {
nextDp[nextValue] += ways;
nextDp[nextValue] %= MOD;
}
}
}
dp = nextDp;
}
long long totalWays = 0;
for (auto item : dp) {
long long lastValue = item.first;
long long ways = item.second;
// The last filled value must also be valid with the right fixed value.
if (llabs(lastValue - rightValue) <= 1) {
totalWays = (totalWays + ways) % MOD;
}
}
return totalWays;
}
int countGoodArrays(vector<int> arr) {
int n = arr.size();
vector<int> fixedPositions;
for (int i = 0; i < n; i++) {
if (arr[i] != 0) {
fixedPositions.push_back(i);
}
}
long long answer = 1;
int firstFixedPosition = fixedPositions[0];
// Fill zeros before the first fixed value.
answer = (answer * countFreeSide(arr[firstFixedPosition], firstFixedPosition)) % MOD;
// Fill zero segments between fixed values.
for (int i = 0; i + 1 < (int)fixedPositions.size(); i++) {
int leftPosition = fixedPositions[i];
int rightPosition = fixedPositions[i + 1];
int zeroCount = rightPosition - leftPosition - 1;
long long ways =
countBetweenFixedValues(arr[leftPosition], arr[rightPosition], zeroCount);
answer = (answer * ways) % MOD;
}
int lastFixedPosition = fixedPositions.back();
// Fill zeros after the last fixed value.
answer =
(answer * countFreeSide(arr[lastFixedPosition], n - 1 - lastFixedPosition)) % MOD;
return (int)answer;
}
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
cout << countGoodArrays(arr) << endl;
return 0;
}