SPOJ DQUERY: TLE даже с битом?
Вот проблема, которую я хочу решить, я использую The Fact That Prefix Sum[i] - Prefix Sum[i-1]
Приводит к тому, что частота становится больше нуля, чтобы идентифицировать отдельные цифры, а затем я устраняю частоту, но даже с BIT я получаю TLE
Дана последовательность из n чисел a1, a2, ..., an и ряда d-запросов.
D-запрос - это пара (i, j) (1 ≤ i ≤ j ≤ n).
Для каждого d-запроса (i, j) вы должны вернуть количество различных элементов в подпоследовательности ai, ai+1, ..., aj.
Input
Line 1: n (1 ≤ n ≤ 30000).
Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j
representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the
subsequence ai, ai+1, ..., aj in a single line.
Example
Input
5
1 1 2 1 3
3
1 5
2 4
3 5
Output
3
2
3
код:
#include <iostream>
#include <algorithm>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
typedef long long int ll;
using namespace std;
void update(ll n, ll val, vector<ll> &b);
ll read(ll n,vector<ll> &b);
ll readsingle(ll n,vector<ll> &b);
void map(vector<ll> &a,vector<ll> &b,ll n) /**** RElative Mapping ***/
{
ll temp;
a.clear();
b.clear();
for(ll i=0; i<n; i++)
{
cin>>temp;
a.push_back(temp);
b.push_back(temp);
}
sort(b.begin(),b.end());
for(ll i=0; i<n; i++)
*(a.begin()+i) = (lower_bound(b.begin(),b.end(),a[i])-b.begin())+1;
b.assign(n+1,0);
}
int main()
{
ll n;
cin>>n;
vector<ll> a,b;
map(a,b,n);
ll t;
cin>>t;
while(t--)
{
ll l ,u;
b.assign(n+1,0);
cin>>l>>u;
l--;/*** Reduce For Zero Based INdex ****/
u--;
for(ll i=l;i<=u;i++)
update(a[i],1,b);
ll cont=0;
for(ll i=l;i<=u;i++)
if(readsingle(a[i],b)>0)
{
cont++;
update(a[i],-readsingle(a[i],b),b); /***Eliminate The Frequency */
}
cout<<cont<<endl;
}
return 0;
}
ll readsingle(ll n,vector<ll> &b)
{
return read(n,b)-read(n-1,b);
}
ll read(ll n,vector<ll> &b)
{
ll sum=0;
for(; n; sum+=b[n],n-=n&-n);
return sum;
}
void update(ll n, ll val, vector<ll> &b)
{
for(; n<=b.size(); b[n]+=val,n+=n&-n);
}
1 ответ
Алгоритм, который вы используете, слишком медленный. Для каждого запроса вы выполняете итерацию по всему диапазону запросов, что уже дает n * q
операции (очевидно, это слишком много). Вот лучшее решение (оно имеет O((n + q) * log n)
время и O(n + q)
Пространственная сложность (это автономное решение):
Давайте отсортируем все запросы по их правому концу (нет необходимости явно сортировать их, вы можете просто добавить запрос в соответствующую позицию (из
0
вn - 1
)).Теперь давайте переберем все позиции в массиве слева направо и сохраним BIT. Каждая позиция в BIT является либо
1
(это означает, что в позиции есть новый элементi
) или же0
(изначально он заполнен нулями).Для каждого элемента
a[i]
: если это первое вхождение этого элемента, просто добавьте его кi
положение в БИТ. В противном случае добавьте-1
в положение предыдущего вхождения этого элемента, а затем добавить1
кi
позиция.Ответ на запрос
(left, right)
это просто сумма для всех элементов изleft
вright
,
Чтобы сохранить последнее вхождение каждого элемента, вы можете использовать карту.
Возможно сделать это онлайн, используя постоянное дерево сегментов (временная сложность была бы той же самой, такая же сложность стала бы O(n * log n + q)
), но здесь это не требуется.