Submission #1168943

#TimeUsernameProblemLanguageResultExecution timeMemory
1168943VahanAbrahamFlooding Wall (BOI24_wall)C++20
70 / 100
5095 ms139952 KiB
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <deque>
#include <unordered_set>
#include <unordered_map>
#include <math.h>
#include <cmath>
#include <vector>
#include <iomanip>
#include <random>
#include <chrono>
#include <bitset>
using namespace std;

#define ll long long
#define fr first
#define sc second
#define pb push_back
#define US freopen(".in", "r", stdin); freopen(".out", "w", stdout);

ll gcd(ll a, ll b)
{
    if (a == 0 || b == 0) {
        return  max(a, b);
    }
    if (a <= b) {
        return gcd(a, b % a);
    }
    else {
        return gcd(a % b, b);
    }
}
ll lcm(ll a, ll b) {
    return (a / gcd(a, b)) * b;
}

const int N = 1000005;
const ll oo = 1000000000000000000, MOD = 1000000007;

int a[4][N], index_1[4][N], n, qan[N], sztr;
ll num_in_index[N], pw[N], pat[N];

struct NODE {
    int size;
    ll v, sm;
};

NODE t[3][4 * N];

void push(int ty, int x) {
    if (t[ty][x].v == 1 || t[ty][x].size == 1) {
        return;
    }
    ll val = t[ty][x].v;
    t[ty][2 * x].sm = t[ty][2 * x].sm * val % MOD;
    t[ty][2 * x + 1].sm = t[ty][2 * x + 1].sm * val % MOD;
    t[ty][2 * x].v = t[ty][2 * x].v * val % MOD;
    t[ty][2 * x + 1].v = t[ty][2 * x + 1].v * val % MOD;
    t[ty][x].v = 1;
}

void build(int ty, int lx, int rx, int x) {
    t[ty][x].v = 1;
    t[ty][x].sm = 0;
    if (lx == rx) {
        t[ty][x].size = 1;
        return;
    }
    int m = (lx + rx) / 2;
    build(ty, lx, m, 2 * x);
    build(ty, m + 1, rx, 2 * x + 1);
    t[ty][x].size = t[ty][2 * x].size + t[ty][2 * x + 1].size;
}

void seet(int id, ll val, int lx, int rx, int x) {
    push(1, x);
    push(2, x);
    if (lx == rx) {
        t[2][x].sm += (num_in_index[lx] * val % MOD);
        if (t[2][x].sm >= MOD) {
            t[2][x].sm -= MOD;
        }
        t[1][x].sm = (t[1][x].sm + val);
        if (t[1][x].sm >= MOD) {
            t[1][x].sm -= MOD;
        }
        return;
    }
    int m = (lx + rx) / 2;
    if (id <= m) {
        seet(id, val, lx, m, 2 * x);
    }
    else {
        seet(id, val, m + 1, rx, 2 * x + 1);
    }
    t[1][x].sm = (t[1][2 * x].sm + t[1][2 * x + 1].sm);
    if (t[1][x].sm >= MOD) {
        t[1][x].sm -= MOD;
    }
    t[2][x].sm = (t[2][2 * x].sm + t[2][2 * x + 1].sm);
    if (t[2][x].sm >= MOD) {
        t[2][x].sm -= MOD;
    }
}

void ubd(int l, int r, int val, int lx, int rx, int x) {
    push(1, x);
    push(2, x);
    if (lx > r || rx < l) {
        return;
    }
    if (l <= lx && rx <= r) {
        t[1][x].sm = t[1][x].sm * (ll)val % MOD;
        t[1][x].v = t[1][x].v * (ll)val % MOD;
        t[2][x].sm = t[2][x].sm * (ll)val % MOD;
        t[2][x].v = t[2][x].v * (ll)val % MOD;
        return;
    }
    int m = (lx + rx) / 2;
    ubd(l, r, val, lx, m, 2 * x);
    ubd(l, r, val, m + 1, rx, 2 * x + 1);
    t[1][x].sm = (t[1][2 * x].sm + t[1][2 * x + 1].sm);
    if (t[1][x].sm >= MOD) {
        t[1][x].sm -= MOD;
    }
    t[2][x].sm = (t[2][2 * x].sm + t[2][2 * x + 1].sm);
    if (t[2][x].sm >= MOD) {
        t[2][x].sm -= MOD;
    }
}

int sum(int ty, int l, int r, int lx, int rx, int x) {
    push(ty, x);
    if (lx > r || rx < l) {
        return 0;
    }
    if (l <= lx && rx <= r) {
        return t[ty][x].sm;
    }
    int m = (lx + rx) / 2;
    int smans = (sum(ty, l, r, lx, m, 2 * x) + sum(ty, l, r, m + 1, rx, 2 * x + 1));
    if (smans >= MOD) {
        smans -= MOD;
    }
    return smans;
}


void solv(int vorna) {
    build(1, 1, sztr, 1);
    build(2, 1, sztr, 1);
    for (int i = 1; i <= n; ++i) {
        int ind2 = i;
        if (vorna == 2) {
            ind2 = n - i + 1;
        }
        int sm2 = sum(1, 1, index_1[2][ind2], 1, sztr, 1);
        int sm1 = sum(1, 1, index_1[1][ind2], 1, sztr, 1);
        ubd(1, index_1[2][ind2] - 1, 0, 1, sztr, 1);
        ubd(index_1[1][ind2] + 1, sztr, 2, 1, sztr, 1);
        if (i != 1) {
            seet(index_1[2][ind2], sm2, 1, sztr, 1);
            seet(index_1[1][ind2], sm1, 1, sztr, 1);
        }
        else {
            seet(index_1[2][ind2], 1, 1, sztr, 1);
            seet(index_1[1][ind2], 1, 1, sztr, 1);
        }
        pat[i] += sum(2, 1, sztr, 1, sztr, 1) * pw[n - i] % MOD;
        pat[i] %= MOD;
    }
}

void solve() {
    cin >> n;
    pw[0] = 1;
    for (int i = 1; i <= n; ++i) {
        pw[i] = pw[i - 1] * 2LL % MOD;
    }
    for (int i = 1; i <= n; ++i) {
        cin >> a[1][i];
    }
    for (int i = 1; i <= n; ++i) {
        cin >> a[2][i];
        if (a[1][i] < a[2][i]) {
            swap(a[1][i], a[2][i]);
        }
    }
    vector <pair<int, pair<int, int>>> vec;
    for (int i = 1; i <= n; ++i) {
        vec.pb({ a[1][i],{i,1} });
        vec.pb({ a[2][i],{i,2} });
    }
    vector<int> index_in_real(vec.size() + 5);
    sort(vec.begin(), vec.end());
    for (int i = 0; i < vec.size(); ++i) {
        num_in_index[i + 1] = vec[i].fr;
        index_in_real[i] = vec[i].sc.fr;
        index_1[vec[i].sc.sc][vec[i].sc.fr] = i + 1;
    }
    sztr = vec.size();
    solv(1);
    for (int i = 1; i <= n / 2; ++i) {
        swap(a[1][i], a[1][n - i + 1]);
        swap(a[2][i], a[2][n - i + 1]);
    }
    solv(2);
    int canstartsmx = 0;
    for (int i = vec.size() - 1; i >= 0; --i) {
        int id_real = index_in_real[i];
        qan[id_real]++;
        if (qan[id_real] == 2) {
            canstartsmx = i;
            break;
        }
    }
    for (int i = vec.size() - 1; i >= 0; --i) {
        int id_real = index_in_real[i];
        qan[id_real] = 0;
    }
    ll ans2 = 0, cnt = 0, ans1 = 0;
    for (int i = 0; i < vec.size(); ++i) {
        if (canstartsmx <= i) {
            ans2 += (ll)n * pw[cnt] % MOD * vec[i].fr % MOD;
            if (ans2 >= MOD) {
                ans2 -= MOD;
            }
        }
        int id_real = index_in_real[i];
        qan[id_real]++;
        if (qan[id_real] == 2) {
            ++cnt;
        }
    }
    for (int i = 1; i <= n; ++i) {
        ans1 += pat[i];
        if (ans1 >= MOD) {
            ans1 -= MOD;
        }
    }
    ll ans3 = 0;
    for (int i = 1; i <= n; ++i) {
        for (int k = 1; k <= 2; ++k) {
            ans3 += (ll)a[k][i] * pw[n - 1] % MOD;
            if (ans3 >= MOD) {
                ans3 -= MOD;
            }
        }
    }
    cout << (ans1 - ans2 + MOD - ans3 + MOD) % MOD << endl;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    //US
    int tt = 1;
    //cin >> tt;
    while (tt--) {
        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...