2023 rcpc

This commit is contained in:
2024-04-22 16:45:09 +03:00
parent a0ddb657b7
commit 156202ada0
61 changed files with 4462 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
/// 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();
}
}