Submission #1267805

#TimeUsernameProblemLanguageResultExecution timeMemory
1267805uranium235Zoltan (COCI16_zoltan)C++17
140 / 140
140 ms12872 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const char nn = '\n';
const ll mod = 1000000007, inv = 500000004;

struct state {
    int max = 0;
    ll count = 0;
    void merge(state &l, state &r) {
        if (l.max > r.max) count = l.count;
        else if (r.max > l.max) count = r.count;
        else count = (l.count + r.count) % mod;
        max = std::max(l.max, r.max);
    }
};

class segtree {
    public:
        int n;
        vector<state> a;
        segtree(int n) : n(n), a(2 * n) {}
        void upd(int i, state &x) {
            for (a[i += n] = x; i > 1; i /= 2) a[i / 2].merge(a[i], a[i ^ 1]);
        }
        state qry(int l, int r) {
            state result;
            for (l += n, r += n; l < r; l /= 2, r /= 2) {
                if (l % 2 == 1) result.merge(result, a[l++]);
                if (r % 2 == 1) result.merge(a[--r], result);
            }
            return result;
        }
        void clear() {
            for (state &i : a) i.count = i.max = 0;
        }
};

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

    int n;
    cin >> n;
    vector<pair<int, int>> a(n);
    vector<int> comp(n), powtwo(n + 1);
    powtwo[0] = 1;
    for (int i = 0; i < n; i++) {
        cin >> comp[i];
        a[i] = {comp[i], i};
        powtwo[i + 1] = powtwo[i] * 2 % mod;
    }
    sort(comp.begin(), comp.end());
    comp.erase(unique(comp.begin(), comp.end()), comp.end());
    sort(a.begin(), a.end(), [](const pair<int, int> &l, const pair<int, int> &r) {
        if (l.first < r.first) return true;
        else if (l.first == r.first) return l.second < r.second;
        return false;
    });
    int ptr = 0;
    for (pair<int, int> &i : a) {
        if (comp[ptr] < i.first) ptr++;
        // cout << "comp " << i.first << " -> " << ptr << endl; 
        i.first = ptr;
    }
    assert(ptr == comp.size() - 1);
    ptr = 0;

    segtree tree(n);
    vector<state> cache(n);
    for (int i = 0; i < n; i++) {
        while (ptr < n && a[ptr].first == i) {
            pair<int, int> &p = a[ptr];
            state get = tree.qry(p.second + 1, n);
            if (get.max++ == 0) get.count = 1;
            tree.upd(p.second, get);
            cache[i].merge(cache[i], get);
            // cout << p.second << " " << get.max << " " << get.count << nn;
            ptr++;
        }
    }
    assert(ptr == n);
    sort(a.begin(), a.end(), [](const pair<int, int> &l, const pair<int, int> &r) {
        if (l.first > r.first) return true;
        else if (l.first == r.first) return l.second < r.second;
        return false;
    });
    tree.clear();
    state total, ans;
    total.count = 1;
    ptr = 0;
    for (int i = n; i >= 0; i--) {
        while (ptr < n && a[ptr].first == i) {
            pair<int, int> &p = a[ptr];
            state get = tree.qry(p.second + 1, n);
            if (get.max++ == 0) get.count = 1;
            tree.upd(p.second, get);
            total.merge(total, get);
            ptr++;
        }
        state curAns = total;
        if (i > 0) {
            curAns.max += cache[i - 1].max;
            curAns.count = curAns.count * cache[i - 1].count % mod;
            // cout << " " << cache[iter - 2].max << " " << cache[iter - 2].count;
        }
        curAns.count = curAns.count * powtwo[n - curAns.max];
        ans.merge(ans, curAns);

        // cout << i << " " << curAns.max << " " << curAns.count << nn;
    }
    assert(ptr == n);
        
    cout << ans.max << " " << (ans.count * inv % mod) << nn;
}
#Verdict Execution timeMemoryGrader output
Fetching results...