Submission #1338585

#TimeUsernameProblemLanguageResultExecution timeMemory
1338585ZicrusFlooding Wall (BOI24_wall)C++20
100 / 100
4100 ms65488 KiB
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
const ll inf = LONG_LONG_MAX / 2;

const ll mod = 1000000007;

vector<ll> c;

struct segtree {
    ll nt = 1;
    struct node {
        ll sum = 0, sumci = 0, lz_mul = 1;
    };
    vector<node> tree;
    
    segtree(ll n) {
        nt = 1;
        while (nt < n) nt *= 2;
        tree = vector<node>(2*nt);
    }

    void prop(ll k) {
        (tree[k].sum *= tree[k].lz_mul) %= mod;
        (tree[k].sumci *= tree[k].lz_mul) %= mod;
        if (k < nt) {
            (tree[2*k].lz_mul *= tree[k].lz_mul) %= mod;
            (tree[2*k+1].lz_mul *= tree[k].lz_mul) %= mod;
        }
        tree[k].lz_mul = 1;
    }

    void point_add(ll x, ll v) { return point_add(1, 0, nt-1, x, v); }
    void point_add(ll k, ll tl, ll tr, ll x, ll v) {
        prop(k);
        if (x < tl || x > tr) return;
        if (tl == tr) {
            (tree[k].sum += v) %= mod;
            (tree[k].sumci += v * c[x]) %= mod;
            return;
        }
        ll mid = tl + (tr - tl) / 2;
        if (x <= mid) point_add(2*k, tl, mid, x, v);
        else point_add(2*k+1, mid+1, tr, x, v);
        tree[k].sum = (tree[2*k].sum * tree[2*k].lz_mul + tree[2*k+1].sum * tree[2*k+1].lz_mul) % mod;
        tree[k].sumci = (tree[2*k].sumci * tree[2*k].lz_mul + tree[2*k+1].sumci * tree[2*k+1].lz_mul) % mod;
    }

    void range_mul(ll l, ll r, ll v) { return range_mul(1, 0, nt-1, l, r, v); }
    void range_mul(ll k, ll tl, ll tr, ll l, ll r, ll v) {
        prop(k);
        if (r < tl || l > tr) return;
        if (l <= tl && r >= tr) {
            (tree[k].lz_mul *= v) %= mod;
            prop(k);
            return;
        }
        ll mid = tl + (tr - tl) / 2;
        range_mul(2*k, tl, mid, l, r, v);
        range_mul(2*k+1, mid+1, tr, l, r, v);
        tree[k].sum = (tree[2*k].sum + tree[2*k+1].sum) % mod;
        tree[k].sumci = (tree[2*k].sumci + tree[2*k+1].sumci) % mod;
    }

    ll range_sum(ll r) { return range_sum(1, 0, nt-1, r) % mod; }
    ll range_sum(ll k, ll tl, ll tr, ll r) {
        prop(k);
        if (r < tl) return 0;
        if (r >= tr) return tree[k].sum;
        ll mid = tl + (tr - tl) / 2;
        if (r <= mid) return range_sum(2*k, tl, mid, r);
        else return (tree[2*k].sum * tree[2*k].lz_mul + range_sum(2*k+1, mid+1, tr, r));
    }

    ll range_eval(ll r) { return range_eval(1, 0, nt-1, r) % mod; }
    ll range_eval(ll k, ll tl, ll tr, ll r) {
        prop(k);
        if (r < tl) return 0;
        if (r >= tr) return c[r+1] * tree[k].sum - tree[k].sumci + mod;
        ll mid = tl + (tr - tl) / 2;
        return (range_eval(2*k, tl, mid, r) + range_eval(2*k+1, mid+1, tr, r)) % mod;
        // c[j] * d.range_sum(j-1) - di.range_sum(j-1)
    }
};

struct segtree2 {
    ll nt = 1;
    struct node {
        ll sum = 0, lz_mul = 1;
    };
    vector<node> tree;
    
    segtree2(ll n) {
        nt = 1;
        while (nt < n) nt *= 2;
        tree = vector<node>(2*nt);
    }

    void prop(ll k) {
        (tree[k].sum *= tree[k].lz_mul) %= mod;
        if (k < nt) {
            (tree[2*k].lz_mul *= tree[k].lz_mul) %= mod;
            (tree[2*k+1].lz_mul *= tree[k].lz_mul) %= mod;
        }
        tree[k].lz_mul = 1;
    }

    void point_add(ll x, ll v) { return point_add(1, 0, nt-1, x, v); }
    void point_add(ll k, ll tl, ll tr, ll x, ll v) {
        prop(k);
        if (x < tl || x > tr) return;
        if (tl == tr) {
            (tree[k].sum += v) %= mod;
            return;
        }
        ll mid = tl + (tr - tl) / 2;
        if (x <= mid) point_add(2*k, tl, mid, x, v);
        else point_add(2*k+1, mid+1, tr, x, v);
        tree[k].sum = (tree[2*k].sum * tree[2*k].lz_mul + tree[2*k+1].sum * tree[2*k+1].lz_mul) % mod;
    }

    void range_mul(ll l, ll r, ll v) { return range_mul(1, 0, nt-1, l, r, v); }
    void range_mul(ll k, ll tl, ll tr, ll l, ll r, ll v) {
        prop(k);
        if (r < tl || l > tr) return;
        if (l <= tl && r >= tr) {
            (tree[k].lz_mul *= v) %= mod;
            prop(k);
            return;
        }
        ll mid = tl + (tr - tl) / 2;
        range_mul(2*k, tl, mid, l, r, v);
        range_mul(2*k+1, mid+1, tr, l, r, v);
        tree[k].sum = (tree[2*k].sum + tree[2*k+1].sum) % mod;
    }

    ll range_sum(ll r) { return range_sum(1, 0, nt-1, r) % mod; }
    ll range_sum(ll k, ll tl, ll tr, ll r) {
        prop(k);
        if (r < tl) return 0;
        if (r >= tr) return tree[k].sum;
        ll mid = tl + (tr - tl) / 2;
        if (r <= mid) return range_sum(2*k, tl, mid, r);
        else return (tree[2*k].sum * tree[2*k].lz_mul + range_sum(2*k+1, mid+1, tr, r));
    }

    void bake(ll k) {
        prop(k);
        if (k >= nt) return;
        bake(2*k);
        bake(2*k+1);
    }
};

ll solve_with_left_wall(ll n, vector<ll> &a, vector<ll> &b) {
    segtree d(sz(c));
    ll base = 0;
    auto eval = [&](ll j) {
        return (base + d.range_eval(j-1)) % mod;
    };
    auto add = [&](ll j, ll v) {
        d.point_add(j, v);
    };
    auto mul = [&](ll l, ll r, ll v) {
        d.range_mul(l, r, v);
    };
    ll pw2 = 1;
    for (ll i = 0; i < n; i++) {
        ll av = eval(a[i]), bv = eval(b[i]);
        base = (av + bv) % mod;
        ll sa = d.range_sum(a[i]-1);
        ll sb = d.range_sum(b[i]-1);
        mul(b[i], sz(c)-1, 2); mul(0, a[i]-1, 0);
        add(b[i], sb+pw2); add(a[i], sa+pw2);
        (pw2 *= 2) %= mod;
    }
    return base;
}

ll solve_filled(ll n, vector<ll> &a, vector<ll> &b) {
    segtree2 hist(sz(c));
    hist.point_add(a[0], 1);
    hist.point_add(b[0], 1);
    ll mn = a[0];
    for (ll i = 1; i < n; i++) {
        ll sb = hist.range_sum(b[i]-1) * (b[i] > mn);
        hist.range_mul(b[i] * (b[i] > mn), sz(c)-1, 2);
        hist.point_add(b[i], sb);
        mn = max(mn, a[i]);
    }
    ll res = 0;
    hist.bake(1);
    hist.tree[hist.nt + mn].sum = hist.range_sum(mn);
    for (ll i = mn; i < sz(c); i++) {
        ll freq = hist.tree[hist.nt + i].sum;
        ll rect = (n * (c.back() - c[i]) % mod);
        (res -= rect * freq) %= mod;
    }
    (res += mod) % mod;
    ll pw2 = 1;
    for (ll i = 0; i < n-1; i++) {
        pw2 = (2 * pw2) % mod;
    }
    for (ll i = 0; i < n; i++) {
        ll v = 0;
        v += c.back() - c[a[i]];
        v += c.back() - c[b[i]];
        (res += pw2 * v) %= mod;
    }
    return res;
}

void solve() {
    ll n; cin >> n;
    vector<ll> a(n), b(n);
    for (auto &e : a) cin >> e;
    for (auto &e : b) cin >> e;
    c.clear();
    for (ll i = 0; i < n; i++) {
        if (a[i] > b[i]) swap(a[i], b[i]);
        c.push_back(a[i]);
        c.push_back(b[i]);
    }
    sort(all(c));
    c.erase(unique(all(c)), c.end());
    for (auto &e : a) e = lower_bound(all(c), e) - c.begin();
    for (auto &e : b) e = lower_bound(all(c), e) - c.begin();

    ll res = mod - solve_filled(n, a, b);
    res += solve_with_left_wall(n, a, b);
    reverse(all(a)); reverse(all(b));
    res += solve_with_left_wall(n, a, b);
    cout << res % mod << '\n';
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    solve();
}
#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...