QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#880728 | #9698. Twenty-two | hos_lyric | WA | 1ms | 19868kb | C++14 | 9.1kb | 2025-02-03 18:55:10 | 2025-02-03 18:55:12 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
////////////////////////////////////////////////////////////////////////////////
template <unsigned M_> struct ModInt {
static constexpr unsigned M = M_;
unsigned x;
constexpr ModInt() : x(0U) {}
constexpr ModInt(unsigned x_) : x(x_ % M) {}
constexpr ModInt(unsigned long long x_) : x(x_ % M) {}
constexpr ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
constexpr ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
ModInt pow(long long e) const {
if (e < 0) return inv().pow(-e);
ModInt a = *this, b = 1U; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
}
ModInt inv() const {
unsigned a = M, b = x; int y = 0, z = 1;
for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
assert(a == 1U); return ModInt(y);
}
ModInt operator+() const { return *this; }
ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0U; return a; }
ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
explicit operator bool() const { return x; }
bool operator==(const ModInt &a) const { return (x == a.x); }
bool operator!=(const ModInt &a) const { return (x != a.x); }
friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
////////////////////////////////////////////////////////////////////////////////
constexpr unsigned MO = 998244353;
using Mint = ModInt<MO>;
void exper() {
// m chmins, n chmaxs
for (int m = 1; m <= 3; ++m) for (int n = 1; n <= 2; ++n) {
string ops = string(m, '0') + string(n, '1');
do {
printf("ops = %s\n", ops.c_str());
vector<int> cs(m + n);
for (int i = 0; i < m + n; ++i) cs[i] = i;
do {
// chmin incr.
if ([&]() -> bool {
int cm = -1;
for (const int c : cs) if (ops[c] == '0') if (!chmax(cm, c)) return false;
return true;
}()) {
int l = -1, r = m + n;
int z = -1;
for (int i = m + n; --i >= 0; ) {
if (ops[cs[i]] == '0') {
chmin(r, cs[i]);
if (l > r) { z = l; break; }
} else {
chmax(l, cs[i]);
if (l > r) { z = r; break; }
}
}
int cnt = 0;
for (int i = 0; i < m + n; ++i) {
if (ops[cs[i]] == '0') {
printf("%s[%d] ", string((n - cnt) * 2, ' ').c_str(), cs[i]);
cnt = 0;
} else {
printf("%d ", cs[i]);
++cnt;
}
}
printf("%s : ", string((n - cnt) * 2, ' ').c_str());
if (l > r) {
printf("%d", z);
} else {
printf("[%d,%d]", l, r);
}
puts("");
// for each chmax, chmined in the nearest future
int mx = -1;
for (int i = 0; i < m + n; ++i) if (ops[cs[i]] == '1') {
int c = cs[i];
for (int j = i + 1; j < m + n; ++j) if (ops[cs[j]] == '0') {
if (chmin(c, cs[j])) break;
}
chmax(mx, c);
}
if (l > r) assert(z == mx);
}
} while (next_permutation(cs.begin(), cs.end()));
puts("");
fflush(stdout);
} while (next_permutation(ops.begin(), ops.end()));
}
}
/*
sample
ops = 0101
[0] 1 [2] 3 : 3
[0] 1 3 [2] : 2
[0] [2] 1 3 : 3
[0] [2] 3 1 : 3
[0] 3 1 [2] : 2
[0] 3 [2] 1 : 2
1 [0] [2] 3 : 3
1 [0] 3 [2] : 2
1 3 [0] [2] : 0
3 [0] 1 [2] : 1
3 [0] [2] 1 : 1
3 1 [0] [2] : 0
*/
/*
backward
chmin(-, c): [-INF, c]
chmax(-, d): [d, +INF]
can ignore the positions where all intervals intersect
chmins: C[0] <= C[1] <= ... <= C[M-1]
chmin incr.
0 = i[0] < i[1] < ... < i[k-1] < M
single chmax(-, d)
insert at: ..., chmin(-, C[i[l-1]]), chmax(-, d), chmin(-, C[i[l]]), ...
if d <= C[i[l]]
[l, r] = [d, C[i[l]]] ~~> finally >= d
other chmax ==> possibly z determined earlier with larger l or with r
if d > C[i[l]]
[l, r] = [*, C[i[l]]] ~~> z = C[i[l]]
other chmax ==> possibly z determined earlier with larger r
can assume all chmins are used
for each chmax(-, d), select d or smaller value in C, then take their max
sample
for [0, 3), chmax(-, d) with d = 2 or 3
for [1, 5), chmax(-, d) with d = 2 or 4 or 5
22222, 24444, 25555, 33322, 34444, 35555
decision
consider min = x
can use any available chmax, so check if:
- OK already
- chmax(-, x) available
- x \in C, chmax(-, d) available s.t. x < d
divide, recurse
counting
dp[x][l][r]: min >= x, (l, r)
transition: all positions of x
l = u[0] -> u[1] -> ... -> u[p-1] -> u[p] = r
*/
constexpr int MAX = 160;
int N, M, K;
vector<int> C;
vector<int> L, R, D;
Mint dp[MAX][MAX][MAX];
bool can[MAX];
Mint sub[MAX];
int main() {
// exper();
for (; ~scanf("%d%d%d", &N, &M, &K); ) {
for (int u = 1; u <= N; ++u) {
scanf("%*d");
}
C.resize(M);
for (int i = 0; i < M; ++i) {
scanf("%d", &C[i]);
}
sort(C.begin(), C.end());
L.resize(K);
R.resize(K);
D.resize(K);
for (int k = 0; k < K; ++k) {
scanf("%d%d%d", &L[k], &R[k], &D[k]);
}
{
vector<int> mxs(N + 1, 0);
for (int k = 0; k < K; ++k) for (int u = L[k]; u <= R[k]; ++u) chmax(mxs[u], D[k]);
vector<int> us;
for (int u = 1; u <= N; ++u) if (mxs[u] > C[0]) us.push_back(u);
N = us.size();
for (int k = 0; k < K; ++k) {
L[k] = lower_bound(us.begin(), us.end(), L[k]) - us.begin() + 1;
R[k] = upper_bound(us.begin(), us.end(), R[k]) - us.begin();
}
}
// cerr<<"N = "<<N<<", L = "<<L<<", R = "<<R<<endl;
memset(dp, 0, sizeof(dp));
for (int l = N; l >= 0; --l) {
dp[N + 1][l][l + 1] = 1;
}
for (int x = N; x >= 1; --x) {
bool inC = false;
for (int i = 0; i < M; ++i) inC = inC || (C[i] == x);
for (int l = N; l >= 0; --l) for (int r = l + 1; r <= N + 1; ++r) {
for (int u = l; u <= r; ++u) can[u] = false;
can[l] = can[r] = true;
for (int k = 0; k < K; ++k) if (l < L[k] && R[k] < r) {
if (inC ? (D[k] >= x) : (D[k] == x)) {
for (int u = L[k]; u <= R[k]; ++u) can[u] = true;
}
}
for (int u = l; u <= r; ++u) sub[u] = 0;
sub[l] = 1;
for (int u = l; u < r; ++u) if (sub[u]) {
for (int v = u + 1; v <= r; ++v) if (can[v]) {
sub[v] += sub[u] * dp[x + 1][u][v];
}
}
dp[x][l][r] += sub[r];
}
}
printf("%u\n", dp[1][0][N + 1].x);
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 19760kb
input:
5 2 2 4 1 3 5 2 2 4 1 3 3 2 5 5
output:
6
result:
ok 1 number(s): "6"
Test #2:
score: -100
Wrong Answer
time: 0ms
memory: 19868kb
input:
13 2 1 12 13 4 12 9 12 11 3 13 1 3 8 10 3 9 6 7 10
output:
0
result:
wrong answer 1st numbers differ - expected: '3', found: '0'