This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 freq;
vi cnts;
set<int> incnt;
struct query
{
int l, r, idx;
};
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 (freq[x] > 0)
{
--cnts[freq[x]];
if (cnts[freq[x]] == 0)
incnt.erase(freq[x]);
}
++freq[x];
++cnts[freq[x]];
if (cnts[freq[x]] == 1)
incnt.insert(freq[x]);
}
void sub(int x)
{
--cnts[freq[x]];
if (cnts[freq[x]] == 0)
incnt.erase(freq[x]);
--freq[x];
if (freq[x])
{
++cnts[freq[x]];
if (cnts[freq[x]] == 1)
incnt.insert(freq[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;
freq.assign(*max_element(all(A)) + 1, 0);
cnts.assign(N + 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;
ll left = 0, right = 0;
ll tmp = totalLengthOfSubsequences(n);
vpii S;
for (int f : incnt)
{
if (cnts[f] & 1)
S.push_back({f, 1});
if (cnts[f] > 1)
{
S.push_back({f, cnts[f] / 2});
S.push_back({f, cnts[f] / 2});
}
}
for (auto it = S.begin(); it != S.end(); ++it)
{
ll x = it->first; // how much
ll y = it->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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |