Submission #1346839

#TimeUsernameProblemLanguageResultExecution timeMemory
1346839JahonaliXZoltan (COCI16_zoltan)C++20
56 / 140
155 ms31648 KiB
#include <bits/stdc++.h>

using namespace std;

#define int long long
constexpr int mod = 1e9 + 7;

struct node { int mx, cnt; };

node merge(node left, node right) {
    if (left.mx > right.mx) return left;
    if (right.mx > left.mx) return right;
    return {left.mx, (left.cnt + right.cnt) % mod};
}

struct segment_tree {
    int n;
    vector<node> t;
    segment_tree(int n) : n(n), t(n << 2, {1, 1}) {}
    void update(int i, int dp, int cn, int v = 1, int l = 0, int r = -1) {
        if (r < 0) r += n;
        if (l == r) t[v] = merge(t[v], {dp, cn});
        else {
            int m = (l + r) >> 1;
            if (i <= m) update(i, dp, cn, v << 1, l, m);
            else update(i, dp, cn, v << 1 | 1, m + 1, r);
            t[v] = merge(t[v << 1], t[v << 1 | 1]);
        }
    }
    node get(int L, int R, int v = 1, int l = 0, int r = -1) {
        if (L > R) return {1, 1};
        if (r < 0) r += n;
        if (L <= l && r <= R) return t[v];
        int m = (l + r) >> 1;
        if (R <= m) return get(L, R, v << 1, l, m);
        if (L > m) return get(L, R, v << 1 | 1, m + 1, r);
        return merge(get(L, R, v << 1, l, m), get(L, R, v << 1 | 1, m + 1, r));
    }
};

int binpow(int x, int y) {
    if (!y) return 1;
    int z = binpow(x, y >> 1);
    z = z * z % mod;
    if (y & 1) z = z * x % mod;
    return z;
}

int32_t main() {
#ifdef JahonaliX
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m;
    cin >> n;
    node ans{0, 0};
    vector<int> a(n), u, pw(n * 2, 1);
    for (int i = 1; i < n * 2; ++i) pw[i] = pw[i - 1] * 2 % mod;
    for (int &i : a) cin >> i, u.emplace_back(i);
    sort(u.begin(), u.end()), u.erase(unique(u.begin(), u.end()), u.end()), m = u.size();
    segment_tree lis(m), lds(m);
    for (int &i : a) i = lower_bound(u.begin(), u.end(), i) - u.begin();
    reverse(a.begin(), a.end());
    for (int i : a) {
        node is = lis.get(0, i - 1), ds = lds.get(i + 1, m - 1), cr = {is.mx + ds.mx - 1, is.cnt * ds.cnt % mod};
        cr.cnt = cr.cnt * pw[n - cr.mx] % mod;
        ans = merge(ans, cr);
        lis.update(i, is.mx + 1, is.cnt), lds.update(i, ds.mx + 1, ds.cnt);
    }
    cout << ans.mx << ' ' << ans.cnt;
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...