제출 #799337

#제출 시각아이디문제언어결과실행 시간메모리
799337JohannDiversity (CEOI21_diversity)C++14
64 / 100
7031 ms4732 KiB
#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef vector<ll> vi;
typedef pair<ll, ll> pii;
typedef vector<pii> vpii;
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()

const ll INF = 1e18;
int N, Q;
vi A;
vi ans;
vi heatmap;
map<int, int> cnts;

struct query
{
    int l, r, idx;
};

vi split(int x)
{
    vi sp;
    if (x == 1)
        sp.push_back(1);
    else
    {
        sp.push_back(x / 2);
        sp.push_back(x / 2);
        if (x & 1)
            sp.push_back(1);
    }
    return sp;
}

ll numberOfSubsequences(ll n)
{
    return n * (n + 1) / 2;
}
ll totalLengthOfSubsequences(ll n)
{
    return n * (n + 1) * (n + 1) / 2 - (2 * n + 1) * (n + 1) * n / 6;
}
void add(int x)
{
    if (heatmap[x] > 0)
    {
        --cnts[heatmap[x]];
        if (cnts[heatmap[x]] == 0)
            cnts.erase(heatmap[x]);
    }
    ++heatmap[x];
    ++cnts[heatmap[x]];
}
void sub(int x)
{
    --cnts[heatmap[x]];
    if (cnts[heatmap[x]] == 0)
        cnts.erase(heatmap[x]);
    --heatmap[x];
    if (heatmap[x])
        ++cnts[heatmap[x]];
}

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

    cin >> N >> Q;
    A.resize(N);
    for (int i = 0; i < N; ++i)
        cin >> A[i];

    vector<query> Qu(Q);
    ans.resize(Q);
    for (int i = 0; i < Q; ++i)
        cin >> Qu[i].l >> Qu[i].r, Qu[i].idx = i, --Qu[i].l;

    int sq = 1;
    while (sq * sq < N)
        ++sq;
    auto cmp = [&](const query &a, const query &b)
    { if (a.l / sq == b.l / sq) 
        return a.r < b.r;
    else
        return a.l < b.l; };
    sort(all(Qu), cmp);

    int lx = 0, rx = 0;
    heatmap.assign(*max_element(all(A)) + 1, 0);
    for (query q : Qu)
    {
        while (rx < q.r)
            add(A[rx++]);
        while (lx > q.l)
            add(A[--lx]);
        while (rx > q.r)
            sub(A[--rx]);
        while (lx < q.l)
            sub(A[lx++]);

        ll n = q.r - q.l;

        vpii S;
        for (auto it = cnts.begin(); it != cnts.end(); ++it)
            for (int x : split(it->second))
                S.push_back({it->first, x});

        int num = sz(S);
        ll left = 0, right = 0;
        ll tmp = totalLengthOfSubsequences(n);

        for (int j = 0; j < num; ++j)
        {

            ll x = S[j].first;  // how much
            ll y = S[j].second; // how often
            ll len = x * y;

            // if both are in set
            tmp -= totalLengthOfSubsequences(len) - x * x * (totalLengthOfSubsequences(y) - y) - y * numberOfSubsequences(x);
            // if one is inside the other isn't
            tmp -= (n - len) * (len * (len + 1) / 2 - x * y * (y + 1) / 2);
            // if both are outside
            tmp -= (len - y) * left * (n - left - len);

            left += len;
            swap(left, right);
        }

        ans[q.idx] = tmp;
    }
    for (ll x : ans)
        cout << x << "\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...