168 lines
2.8 KiB
C++
168 lines
2.8 KiB
C++
/// Ionita Alexandru
|
|
#include <bits/stdc++.h>
|
|
#define st first
|
|
#define nd second
|
|
|
|
using namespace std;
|
|
|
|
const long long N = 500100;
|
|
long long n, aib[N], a[N], prev, f[N];
|
|
string s;
|
|
|
|
const long long MOD = 1e9 + 7;
|
|
|
|
long long powMod(long long a, long long exp) {
|
|
long long b = a, res = 1;
|
|
while(exp) {
|
|
if(exp % 2) res *= b;
|
|
b = 1LL * b * b % MOD;
|
|
res %= MOD;
|
|
exp /= 2;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
long long invMod(long long x) {
|
|
return powMod(x, MOD - 2);
|
|
}
|
|
|
|
long long comb(long long n, long long k) {
|
|
if(n < k) return 0;
|
|
if(n == k) return 1;
|
|
if(k == 0) return 1;
|
|
return f[n] * invMod(1LL * f[k] * f[n - k] % MOD) % MOD;
|
|
}
|
|
|
|
long long lsb(long long x) {
|
|
return x & (-x);
|
|
}
|
|
|
|
void upd(long long pos, long long val) {
|
|
for(; pos < N; pos += lsb(pos)) {
|
|
aib[pos] += val;
|
|
}
|
|
}
|
|
|
|
long long que(long long pos) {
|
|
long long ret = 0;
|
|
for(; pos; pos -= lsb(pos)) {
|
|
ret += aib[pos];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
long long que(long long l, long long r) {
|
|
if(l == r && r == 0) return 0;
|
|
if(l == 1) return que(r);
|
|
return que(r) - que(l - 1);
|
|
}
|
|
|
|
|
|
long long compute(long long pos, long long mn, long long mx) {
|
|
|
|
long long prev = pos;
|
|
long long ans = 1;
|
|
|
|
for(long long i = pos + 1; i <= n; i++) {
|
|
if(a[i] == 0) continue;
|
|
if(a[prev] > a[i]) {
|
|
// minim
|
|
long long k = mn - a[i] - 1;
|
|
long long lg = i - prev - 1;
|
|
ans = ans * comb(lg, k) % MOD;
|
|
mn = a[i];
|
|
mx += lg - k;
|
|
if(mx > n) return 0; // todo testcase
|
|
upd(a[i], -1);
|
|
} else {
|
|
long long k = a[i] - mx - 1;
|
|
long long lg = i - prev - 1;
|
|
ans = ans * comb(lg, k) % MOD;
|
|
mx = a[i];
|
|
mn -= lg - k;
|
|
if(mn < 1) return 0;
|
|
upd(a[i], -1);
|
|
}
|
|
long long banned = que(mn, mx);
|
|
if(banned != 1)
|
|
return 0;
|
|
prev = i;
|
|
}
|
|
return ans;
|
|
|
|
}
|
|
|
|
|
|
void solve() {
|
|
long long mn, mx, ans1 = 0, ans2 = 0, banned;
|
|
|
|
cin >> n;
|
|
|
|
f[0] = 1;
|
|
for(long long i = 1; i <= n + 1; i++)
|
|
if(que(i, i) == 1)
|
|
upd(i, -1);
|
|
|
|
for(long long i = 1; i <= n; i++) {
|
|
f[i] = f[i - 1] * i % MOD;
|
|
cin >> a[i];
|
|
if(a[i])
|
|
upd(a[i], 1);
|
|
}
|
|
|
|
long long prev = 0;
|
|
|
|
n++;
|
|
a[n] = n;
|
|
f[n] = f[n - 1] * n % MOD;
|
|
upd(a[n], 1);
|
|
|
|
for(long long i = 1; i <= n; i++) {
|
|
if(a[i]) {
|
|
|
|
mn = a[i];
|
|
mx = a[i] + i - 1;
|
|
if(mx <= n) {
|
|
banned = que(mn, mx);
|
|
if(banned == 1) {
|
|
ans1 = powMod(2, max(i - 2, 0LL));
|
|
ans1 = ans1 * compute(i, mn, mx) % MOD;
|
|
}
|
|
}
|
|
|
|
if(i == 1) break;
|
|
|
|
// memset(aib, 0, sizeof aib);
|
|
|
|
for(long long j = 1; j <= n; j++)
|
|
if(a[j] && que(a[j], a[j]) == 0)
|
|
upd(a[j], 1);
|
|
|
|
mx = a[i];
|
|
mn = a[i] - i + 1;
|
|
if(mn > 0) {
|
|
banned = que(mn, mx);
|
|
if(banned == 1) {
|
|
ans2 = powMod(2, max(i - 2, 0LL));
|
|
ans2 = ans2 * compute(i, mn, mx) % MOD;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
cout << (ans1 + ans2) % MOD << '\n';
|
|
}
|
|
|
|
|
|
int main() {
|
|
int t;
|
|
ios_base::sync_with_stdio(false);
|
|
|
|
cin >> t;
|
|
|
|
for(int i = 1; i <= t; i++) {
|
|
solve();
|
|
}
|
|
|
|
|
|
}
|