删除重复的元素并给出一个范围总和

Remove repeated elements and give a Range Sum

本文关键字:一个 范围 元素 删除      更新时间:2023-10-16

我有一个问题已经问了这个问题:spoj dquery:即使有点?

如果我想在进行范围查询时不考虑重复的元素来计算该怎么办?以下是一个示例:

Input
Line 1: n (1 ≤ n ≤ 10^6).
Line 2: n numbers a1, a2, ..., an (-10^9 ≤ ai ≤ ).
Line 3: q (1 ≤ q ≤ 10^6), 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
9
1 2 3 2 4 1 2 3 4
3
1 9
2 4
5 9
2 7
Output
0          //Explanation: all elements have been repeated.
1          //Explanation: only 3 has not repeated.
3          //Explanation: only 4 is repeated, so count only 1, 2 and 3.
3          //Explanation: only 2 is repeated, so count only 3, 4 and 1.

在@kraskevich的答案中应该做的必要更改是什么(这是该特定情况的有效解决方案(?我试图在上述解决方案中进行 add 0,而不是在上述解决方案中进行-1,这对所有类型的查询都无济于事。有人可以给我一个主意吗?

我最终使用MOS算法做到了它。以下将按预期工作。

/** For the given set of queries find the Unique element
 *  count of an array using MO's Algorithum. */
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <unordered_map>
using namespace std;
struct Query   // struct for storing the queries
{
    int Left;
    int Right;
    int Index;
};
inline void Add(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
    ++countArray[Arr[i]];
    if(countArray[Arr[i]] == 1)
            ans += countArray[Arr[i]];
    if(countArray[Arr[i]] == 2)
            ans -= countArray[Arr[i]];
}

inline  void Remove(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
    --countArray[Arr[i]];
    if(countArray[Arr[i]] == 1)
            ans += countArray[Arr[i]];
    if(countArray[Arr[i]] == 0)
            ans -= countArray[Arr[i]];
}
int main()
{
    int _size;    cin >> _size;
    vector<int> Arr;                            Arr.reserve(_size);
    copy_n(istream_iterator<int>(cin), _size, back_inserter(Arr));
    //copy(Arr.cbegin(), Arr.cend(), ostream_iterator<int>(cout, "t"));
    int id = -1;
    int sqrt_n = sqrt(_size);
    int Q;      cin >> Q;
    vector<Query> qArr(Q);
    unordered_map<int, int> Map;
    for (int i = 0; i < _size; ++i)
    {
        if (Map.count(Arr[i]) == 0)
            Map[Arr[i]] = ++id;
        Arr[i] = Map[Arr[i]];
    }
    // read queries
    for (int i = 0; i < Q; ++i)
    {
        int L,R;
        cin >> L >> R;
        qArr[i].Left  = L-1;
        qArr[i].Right = R-1;
        qArr[i].Index = i;
    }
    // sort the queries according to(MO's Algorithum)
    sort(qArr.begin(),qArr.end(),
         [&](const Query &lhs, const Query &rhs)->bool
         {
             return ( (lhs.Left/sqrt_n == rhs.Left/sqrt_n) ?
                                    lhs.Right < rhs.Right:  // Qs with same Left case
              (lhs.Left / sqrt_n) < (rhs.Left / sqrt_n) );  // Qs with diff values case
         });
    int currStart = 0;
    int currEnd   = 0;
    int tempAnswer= 0;
    vector<int> Answer(Q);
    vector<int> countArray(_size);
    for (int i = 0; i < Q; ++i)
    {
        int L = qArr[i].Left;
        int R = qArr[i].Right;
/** Remove extra elements of previous range. For
 *  example if previous range is [0, 3] and current
 *  range is [2, 5], then a[0] and a[1] are subtracted */
        while (currStart < L)
        {
            Remove(currStart, tempAnswer, Arr, countArray);
            ++currStart;
        }
/** Add Elements of current Range */
        while (currStart > L)
        {
            Add(currStart - 1, tempAnswer, Arr, countArray);
            --currStart;
        }
        while (currEnd <= R)
        {
            Add(currEnd, tempAnswer, Arr, countArray);
            ++currEnd;
        }
/** Remove elements of previous range.  For example
 *  when previous range is [0, 10] and current range
 *  is [3, 8], then a[9] and a[10] are subtracted   */
        while (currEnd > R + 1)
        {
            Remove(currEnd - 1, tempAnswer, Arr, countArray);
            --currEnd;
        }
        Answer[qArr[i].Index] = tempAnswer;
    }
    for(const auto &it: Answer) cout<<it<<endl;
    return 0;
}