Submission #1324657

#TimeUsernameProblemLanguageResultExecution timeMemory
1324657lesinhhungFlooding Wall (BOI24_wall)C++20
100 / 100
1329 ms142844 KiB
#include <bits/stdc++.h>
using namespace std;

static const long long MOD = 1000000007LL;

static inline long long mod_add(long long a, long long b) {
    a += b;
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
    return a;
}
static inline long long mod_mul(long long a, long long b) {
    return (a * b) % MOD;
}

struct SegTree {
    int n;                 // size rounded to power of 2
    int orig_n;
    vector<long long> prod;
    vector<long long> sum;
    vector<long long> w;   // weights for positions 1..orig_n (stored 0-based)

    SegTree() : n(0), orig_n(0) {}

    SegTree(int N, const vector<long long>& weights) { init(N, weights); }

    void init(int N, const vector<long long>& weights) {
        orig_n = N;
        w = weights;
        n = 1;
        while (n < N) n <<= 1;
        prod.assign(2 * n, 1);
        sum.assign(2 * n, 0);
        // initialize leaves with c=0 => prod=0, sum=0
        for (int i = 0; i < n; i++) {
            int idx = n + i;
            if (i < orig_n) {
                prod[idx] = 0;
                sum[idx] = 0;
            } else {
                // neutral for empty slots: prod=1, sum=0
                prod[idx] = 1;
                sum[idx] = 0;
            }
        }
        for (int i = n - 1; i >= 1; --i) pull(i);
    }

    void pull(int v) {
        long long pl = prod[v << 1];
        long long pr = prod[v << 1 | 1];
        prod[v] = mod_mul(pl, pr);
        sum[v] = mod_add(sum[v << 1], mod_mul(pl, sum[v << 1 | 1]));
    }

    // set position pos (1-based) to value c in {0,1,2}
    void set_val(int pos1, int c) {
        int pos = pos1 - 1;
        int v = n + pos;
        prod[v] = (pos < orig_n ? (long long)c : 1LL);
        sum[v] = (pos < orig_n ? mod_mul(w[pos], (long long)c) : 0LL);
        v >>= 1;
        while (v) {
            pull(v);
            v >>= 1;
        }
    }

    long long all_prod() const { return prod[1]; }
    long long weighted_prefix_sum() const { return sum[1]; }
};

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

    int N;
    cin >> N;
    vector<long long> a(N + 1), b(N + 1);
    vector<long long> vals;
    vals.reserve(2 * N);
    for (int i = 1; i <= N; i++) {
        cin >> a[i];
        vals.push_back(a[i]);
    }
    for (int i = 1; i <= N; i++) {
        cin >> b[i];
        vals.push_back(b[i]);
    }

    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    int M = (int)vals.size();

    vector<long long> pow2(N + 1, 1);
    for (int i = 1; i <= N; i++) pow2[i] = (pow2[i - 1] * 2) % MOD;

    // weights w_i = 2^(N-i) for i=1..N
    vector<long long> w(N);
    for (int i = 1; i <= N; i++) w[i - 1] = pow2[N - i];

    SegTree segF(N, w);
    SegTree segR(N, w);

    // events at value index k: update indices to c=1 or c=2 when threshold V = vals[k]
    vector<vector<int>> ev1(M), ev2(M);
    ev1.shrink_to_fit();
    ev2.shrink_to_fit();

    for (int i = 1; i <= N; i++) {
        long long lo = min(a[i], b[i]);
        long long hi = max(a[i], b[i]);

        int k1 = upper_bound(vals.begin(), vals.end(), lo) - vals.begin();
        int k2 = upper_bound(vals.begin(), vals.end(), hi) - vals.begin();

        if (k1 < M) ev1[k1].push_back(i);
        if (k2 < M) ev2[k2].push_back(i);
    }

    long long total_levels = 0;
    long long prev = 0;

    long long twoN = pow2[N];

    for (int k = 0; k < M; k++) {
        for (int idx : ev1[k]) {
            segF.set_val(idx, 1);
            segR.set_val(N - idx + 1, 1);
        }
        for (int idx : ev2[k]) {
            segF.set_val(idx, 2);
            segR.set_val(N - idx + 1, 2);
        }

        long long A = segF.weighted_prefix_sum(); // sum_i 2^(N-i) * prod_{1..i} c
        long long B = segR.weighted_prefix_sum(); // sum over reversed => sum_i 2^(i-1) * prod_{i..N} c
        long long Pall = segF.all_prod();          // prod_{1..N} c

        long long S = ( (long long)N % MOD ) * twoN % MOD;
        S = mod_add(S, -A);
        S = mod_add(S, -B);
        S = mod_add(S, mod_mul((long long)N % MOD, Pall));

        long long delta = (vals[k] - prev) % MOD;
        total_levels = mod_add(total_levels, mod_mul(delta, S));

        prev = vals[k];
    }

    long long sum_heights = 0;
    long long coef = pow2[N - 1]; // each position chosen in half configs
    for (int i = 1; i <= N; i++) {
        long long s = (a[i] + b[i]) % MOD;
        sum_heights = mod_add(sum_heights, mod_mul(s, coef));
    }

    long long ans = mod_add(total_levels, -sum_heights);
    cout << ans % MOD << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...