AtCoder Beginner Contest 351 F - Double Sum

fhyu發表於2024-05-15

題目連結
\(\displaystyle \sum_{i=1}^N \sum_{j=i+1}^N \max(A_j - A_i, 0)\)
Hint: 可以透過兩個樹狀陣列,第一個維護\(\leq c_i\)的數值和,第二個維護\(\leq c_i\)的個數,需要離散化

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
//#define int long long
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int base = 131;
const int inf = INT_MAX;
const int mod = 1e9 + 7;
const int N = 4e5 + 5;

int n;
vector<int> a(N), cnt(N);
vector<ll> sum(N);

int lowbit(int x) {return x & -x;}
void upd(int x, int d) {
    while (x <= n) {
        sum[x] += d;
        x += lowbit(x);
    }
}
ll query(int x) {
    ll ans = 0;
    while (x) {
        ans += sum[x];
        x -= lowbit(x);
    }
    return ans;
}
void upd1(int x, int d) {
    while (x <= n) {
        cnt[x] += d;
        x += lowbit(x);
    }
}
int query1(int x) {
    int ans = 0;
    while (x) {
        ans += cnt[x];
        x -= lowbit(x);
    }
    return ans;
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    vector<int> v = a;
    vector<int> c(n + 1);
    sort(v.begin() + 1, v.begin() + 1 + n);
    int len = unique(v.begin() + 1, v.begin() + 1 + n) - v.begin() - 1;
    for (int i = 1; i <= n; i++) {
        c[i] = lower_bound(v.begin() + 1, v.begin() + 1 + len, a[i]) - v.begin();
        //cout << c[i] << " \n"[i == n];
    }
    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        upd(c[i], a[i]);
        upd1(c[i], 1);
        ans += 1LL * query1(c[i]) * a[i] - query(c[i]);
    }
    cout << ans << endl;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;
    //cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

相關文章