제출 #1344907

#제출 시각아이디문제언어결과실행 시간메모리
1344907rwangZoltan (COCI16_zoltan)C++20
98 / 140
199 ms18424 KiB
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5, MOD = 1e9 + 7;

//we're looking for LIS and LDS STARTING at an index; NOT ending!

struct Segment {
    long long len, cnt;
} segtree[2][4 * N];//store LIS and LDS

Segment merge(Segment a, Segment b) {
    if (a.len < 0) {
        return b;
    }
    if (b.len < 0) {
        return a;
    }
    if (a.len > b.len) {
        return a;
    }
    if (b.len > a.len) {
        return b;
    }
    return {a.len, a.cnt + b.cnt};
}

void update(int i, int l, int r, int x, Segment v, int t) {
    if (l == r) {
        segtree[t][i] = v;
        return;
    }
    int m = (l + r) / 2;
    if (x <= m) {
        update(2 * i, l, m, x, v, t);
    } else {
        update(2 * i + 1, m + 1, r, x, v, t);
    }
    segtree[t][i] = merge(segtree[t][2 * i], segtree[t][2 * i + 1]);
}

Segment query(int i, int l, int r, int x, int y, int t) {
    if (x > y) {
        return {-1, -1};
    }
    if (l == x && r == y) {
        return segtree[t][i];
    }
    int m = (l + r) / 2;
    return merge(
        query(2 * i, l, m, x, min(m, y), t),
        query(2 * i + 1, m + 1, r, max(m + 1, x), y, t)
    );
}

bool cmp1(const pair<int, int>& a, const pair<int, int>& b) {
    if (a.first != b.first) {
        return a.first > b.first;
    }
    return a.second < b.second;
}

bool cmp2(const pair<int, int>& a, const pair<int, int>& b) {
    if (a.first != b.first) {
        return a.first < b.first;
    }
    return a.second < b.second;
}

long long exp(long long a, long long b) {
    long long ans = 1;
    while (b) {
        if (b & 1) {
            ans = ans * a % MOD;
        }
        a = a * a % MOD;
        b /= 2;
    }
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    pair<int, int> a[N];//value, index
    for (int i = 0; i < n; i++) {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a, a + n, cmp1);
    for (int i = 0; i < n; i++) {
        Segment ans = query(1, 0, n - 1, a[i].second + 1, n - 1, 0);
        if (ans.len <= 0) {
            ans = {0, 1};
        }
        ans.len++;
        update(1, 0, n - 1, a[i].second, ans, 0);
    }
    sort(a, a + n, cmp2);
    for (int i = 0; i < n; i++) {
        Segment ans = query(1, 0, n - 1, a[i].second + 1, n - 1, 1);
        if (ans.len <= 0) {
            ans = {0, 1};
        }
        ans.len++;
        update(1, 0, n - 1, a[i].second, ans, 1);
    }
    long long len = 0, cnt = 0;
    for (int i = 0; i < n; i++) {
        Segment ans1 = query(1, 0, n - 1, i, i, 0);
        Segment ans2 = query(1, 0, n - 1, i, i, 1);
        if (ans1.len + ans2.len - 1 > len) {
            len = ans1.len + ans2.len - 1;
            cnt = ans1.cnt * ans2.cnt % MOD;
        } else if (ans1.len + ans2.len - 1 == len) {
            cnt += ans1.cnt * ans2.cnt % MOD;
            cnt %= MOD;
        }
    }
    cout << len << " " << cnt * exp(2, n - len) % MOD;
}
#Verdict Execution timeMemoryGrader output
Fetching results...