Skip to content

http://poj.openjudge.cn/practice/C26J/

C++
#include <bits/stdc++.h>
using namespace std;

static const int MOD = 167772161;

inline void addmod(int &x, int y) {
    x += y;
    if (x >= MOD) x -= MOD;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m, k;
    cin >> n >> m >> k;

    vector<int> b(n + 1);
    vector<int> missPos;
    vector<int> seen(n, 0);

    for (int i = 1; i <= n; ++i) {
        cin >> b[i];
        if (b[i] == -1) {
            missPos.push_back(i);
        } else {
            seen[b[i]] = 1;
        }
    }

    vector<int> missVal;
    for (int v = 0; v < n; ++v) {
        if (!seen[v]) missVal.push_back(v);
    }

    const int INF = 1e9;

    vector<int> pref(n + 1, INF), suff(n + 2, INF);

    for (int i = 1; i <= n; ++i) {
        pref[i] = pref[i - 1];
        if (b[i] >= 0) pref[i] = min(pref[i], b[i]);
    }

    for (int i = n; i >= 1; --i) {
        suff[i] = suff[i + 1];
        if (b[i] >= 0) suff[i] = min(suff[i], b[i]);
    }

    vector<vector<int>> maxp(k + 2, vector<int>(k + 2, 0));

    for (int qi = 0; qi < m; ++qi) {
        int l, r;
        cin >> l >> r;

        int alpha = int(lower_bound(missPos.begin(), missPos.end(), l) - missPos.begin());
        int beta = int(upper_bound(missPos.begin(), missPos.end(), r) - missPos.begin());

        int len = beta - alpha;

        int c = min(pref[l - 1], suff[r + 1]);
        if (c >= INF) c = n;

        int p = int(lower_bound(missVal.begin(), missVal.end(), c) - missVal.begin());

        if (p == 0 || len == 0 || len == k) continue;

        int L = alpha + 1;
        int R = beta;

        maxp[L][R] = max(maxp[L][R], p);
    }

    vector<vector<int>> mx(k + 2, vector<int>(k + 3));
    vector<vector<int>> mn(k + 2, vector<int>(k + 3));

    vector<vector<int>> clL(k + 2, vector<int>(k + 2));
    vector<vector<int>> clR(k + 2, vector<int>(k + 2));

    auto build_closure = [&](int t) {
        for (int i = 0; i <= k + 1; ++i) {
            fill(mx[i].begin(), mx[i].end(), 0);
            fill(mn[i].begin(), mn[i].end(), k + 1);
        }

        for (int l = 1; l <= k; ++l) {
            for (int r = l; r <= k; ++r) {
                if (maxp[l][r] >= t) {
                    mx[l][r] = l;
                    mn[l][r] = r;
                }
            }
        }

        for (int L = 1; L <= k; ++L) {
            for (int R = k; R >= 1; --R) {
                mx[L][R] = max(mx[L][R], mx[L - 1][R]);
                mx[L][R] = max(mx[L][R], mx[L][R + 1]);

                mn[L][R] = min(mn[L][R], mn[L - 1][R]);
                mn[L][R] = min(mn[L][R], mn[L][R + 1]);
            }
        }

        for (int L = 1; L <= k; ++L) {
            for (int R = L; R <= k; ++R) {
                if (mx[L][R] == 0) {
                    clL[L][R] = 1;
                    clR[L][R] = k;
                } else {
                    clL[L][R] = mx[L][R];
                    clR[L][R] = mn[L][R];
                }
            }
        }
    };

    vector<vector<int>> dp(k + 2, vector<int>(k + 2, 0));
    vector<vector<int>> temp(k + 2, vector<int>(k + 2, 0));
    vector<vector<int>> ndp(k + 2, vector<int>(k + 2, 0));

    vector<vector<int>> rowPref(k + 2, vector<int>(k + 2, 0));
    vector<vector<int>> colSuf(k + 2, vector<int>(k + 2, 0));
    vector<vector<int>> start(k + 2, vector<int>(k + 2, 0));

    build_closure(1);

    for (int q = 1; q <= k; ++q) {
        dp[clL[q][q]][clR[q][q]] = 1;
    }

    for (int t = 2; t <= k; ++t) {
        build_closure(t);

        for (int i = 0; i <= k + 1; ++i) {
            fill(temp[i].begin(), temp[i].end(), 0);
            fill(ndp[i].begin(), ndp[i].end(), 0);
            fill(rowPref[i].begin(), rowPref[i].end(), 0);
            fill(colSuf[i].begin(), colSuf[i].end(), 0);
            fill(start[i].begin(), start[i].end(), 0);
        }

        for (int L = 1; L <= k; ++L) {
            for (int R = L; R <= k; ++R) {
                int val = dp[L][R];
                if (!val) continue;

                int a = clL[L][R];
                int b2 = clR[L][R];

                addmod(temp[a][b2], val);
            }
        }

        for (int a = 1; a <= k; ++a) {
            int s = 0;
            for (int b2 = a; b2 <= k; ++b2) {
                addmod(s, temp[a][b2]);
                rowPref[a][b2] = s;
            }
        }

        for (int b2 = 1; b2 <= k; ++b2) {
            int s = 0;
            for (int a = b2; a >= 1; --a) {
                addmod(s, temp[a][b2]);
                colSuf[b2][a] = s;
            }
        }

        for (int x = 1; x <= k; ++x) {
            int b2 = x;

            while (b2 <= k) {
                int L = clL[x][b2];
                int R = clR[x][b2];
                int s = b2;

                while (b2 + 1 <= k &&
                       clL[x][b2 + 1] == L &&
                       clR[x][b2 + 1] == R) {
                    ++b2;
                }

                if (L == x) {
                    start[x][R] = s;
                }

                ++b2;
            }
        }

        for (int L = 1; L <= k; ++L) {
            for (int R = L; R <= k; ++R) {
                int val = temp[L][R];
                if (val && R - L + 1 >= t) {
                    addmod(ndp[L][R], val);
                }
            }
        }

        for (int b2 = 1; b2 <= k; ++b2) {
            for (int q = 1; q < b2; ++q) {
                int L = clL[q][b2];
                int R = clR[q][b2];

                if (L == q) {
                    int add = colSuf[b2][q + 1];
                    if (add) addmod(ndp[L][R], add);
                }
            }
        }

        for (int a = 1; a <= k; ++a) {
            for (int q = a + 1; q <= k; ++q) {
                int L = clL[a][q];
                int R = clR[a][q];

                if (R != q) continue;

                int add = 0;

                if (L < a) {
                    int s = start[L][R];

                    if (s > a) {
                        add = rowPref[a][s - 1];
                    }
                } else {
                    add = rowPref[a][q - 1];
                }

                if (add) addmod(ndp[L][R], add);
            }
        }

        dp.swap(ndp);
    }

    int ans = 0;

    for (int L = 1; L <= k; ++L) {
        for (int R = L; R <= k; ++R) {
            addmod(ans, dp[L][R]);
        }
    }

    cout << ans << '\n';
    return 0;
}