简体   繁体   English

如何找到给定数字的频率进入数组的范围?

[英]How do I find the frequency of a given number into a range into an array?

The problem is: You are given an array of size N . 问题是:给您一个大小为N的数组。 Also given q =number of queries; 还给出q =查询数; in queries you will be given l =lower range, u =upper range and num =the number of which you will have to count frequency into l~u. 在查询中,您将得到l =较低范围, u =较高范围, num =必须将频率计入l〜u的数量。

I've implemented my code in C++ as follows: 我已经在C ++中实现了我的代码,如下所示:

#include <iostream>
#include <map>

using namespace std;

map<int,int>m;

void mapnumbers(int arr[], int l, int u)
{
    for(int i=l; i<u; i++)
    {
        int num=arr[i];
        m[num]++;
    }
}


int main()
{
    int n; //Size of array
    cin>>n;

    int arr[n];

    for(int i=0; i<n; i++)
        cin>>arr[i];

    int q; //Number of queries
    cin>>q;

    while(q--)
    {
        int l,u,num;   //l=lower range, u=upper range, num=the number of which we will count frequency
        cin>>l>>u>>num;
        mapnumbers(arr,l,u);
        cout<<m[num]<<endl;
    }

    return 0;
}

But my code has a problem, in each query it doesn't make the map m empty. 但我的代码有一个问题,在每个查询它不会使图M空。 That's why if I query for the same number twice/thrice it adds the count of frequency with the previous stored one. 这就是为什么如果我两次/三次查询相同的数字,则会将频率计数与先前存储的频率相加。

How do I solve this? 我该如何解决? Will it be a poor program for a large range of query as 10^5? 对于10 ^ 5的大范围查询,它会是一个糟糕的程序吗? What is an efficient solution for this problem? 什么是解决此问题的有效方法?

You can solve the task using SQRT-decomposition of queries. 您可以使用SQRT分解查询来解决任务。 The complexity will be O(m*sqrt(n)). 复杂度将为O(m * sqrt(n))。 First of all, sort all queries due to the following criteria: L/sqrt(N) should be increasing, where L is the left bound of query. 首先,根据以下条件对所有查询进行排序:L / sqrt(N)应该增加,其中L是查询的左边界。 For equal L/sqrt(N), R (right bounds) should be increasing too. 对于相等的L / sqrt(N),R(右边界)也应增加。 N is the number of queries. N是查询数。 Then do this: calculate answer for first query. 然后执行以下操作:计算第一个查询的答案。 Then, just move the bounds of this query to the bounds of the next query one by one. 然后,只需将此查询的边界一个接一个地移动下一个查询的边界。 For example, if your first query after sort is [2,7] and second is [1, 10], move left bound to 1 and decrease the frequency of a[2], increase the frequency of a 1 . 例如,如果第一个查询后排序是[2,7]和第二为[1,10],向左移动绑定到1和减少的[2],增加的频率的频率1 Move the right bound from 7 to 10. Increase the frequency of a[8], a[9] and a[10]. 将右边界从7移到10。增加a [8],a [9]和a [10]的频率。 Increase and decrease frequencies using your map. 使用地图增加和减少频率。 This is a very complicated technique, but it allows to solve your task with good complexity. 这是一种非常复杂的技术,但是它可以很好地解决您的任务。 You can read more about SQRT-decomposition of queries here: LINK 您可以在此处阅读有关SQRT分解查询的更多信息: LINK

To clear the map, you need to call map::clear() : 要清除地图,您需要调用map::clear()

void mapnumbers(int arr[], int l, int u)
{
    m.clear()

A better approach to the clearing problem is to make m a local variable for the while (q--) loop, or even for the mapnumbers function. 解决清除问题的一种更好的方法是将m用作while (q--)循环甚至mapnumbers函数的局部变量。

However, in general it is very strange why you need map at all. 但是,总的来说,为什么根本不需要地图是很奇怪的。 You traverse the whole array anyway, and you know the number you need to count, so why not do 无论如何,您遍历整个数组,并且知道需要计数的数字,所以为什么不这样做

int mapnumbers(int arr[], int l, int u, int num)
{
    int result = 0;
    for(int i=l; i<u; i++)
    {
        if (arr[i] == num);
            result ++;
    }
    return result;
}

This will be faster, even asymptotically faster, as map operations are O(log N), so your original solution ran for O(N log N) per query, while this simple iteration runs for O(N). 由于map操作为O(log N),因此会更快,甚至渐近更快,因此您的原始解决方案针对每个查询运行O(N log N),而此简单迭代针对O(N)运行。

However, for a really big array and many queries (I guess the problem comes from some competitive programming site, does not it?), this still will not be enough. 但是,对于一个非常大的数组和许多查询(我想问题是来自某个竞争性编程网站,不是吗?),这仍然是不够的。 I guess there should be some data structure and algorithm that allows for O(log N) query, though I can not think of any right now. 我想应该有一些数据结构和算法可以允许O(log N)查询,尽管我现在想不起来。

UPD: I have just realized that the array does not change in your problem. UPD:我刚刚意识到阵列不会改变您的问题。 This makes it much simpler, allowing for a simple O(log N) per query solution. 这使其更简单,每个查询解决方案允许一个简单的O(log N)。 You just need to sort all the numbers in the input array, remembering their original positions too (and making sure the sort is stable, so that the original positions are in increasing order); 您只需要对输入数组中的所有数字进行排序,也要记住它们的原始位置(并确保排序是稳定的,以便原始位置按升序排列); you can do this only once. 您只能执行一次。 After this, every query can be solved with just two binary searches. 此后,只需两个二进制搜索即可解决每个查询。

Many Algorithms are available for this kind of problems . 许多算法可用于此类问题。 This looks like a straight forward data structure problem . 这看起来像一个简单的数据结构问题。 You can use Segment tree , Square Root Decomposition . 您可以使用段树,平方根分解。 Check Geeksforgeeks for the algorithm ! 检查Geeksforgeeks的算法! The reason i am telling you to learn algorithm is , this kind of problems have such large constrains , your verdict will be TLE if you use your method . 我告诉您学习算法的原因是,这种问题有很大的限制,如果您使用方法,您的裁决将是TLE。 So better using Algorithms . 所以使用算法更好。

Many answers here are much way complicated. 这里的许多答案非常复杂。 I am going to tell you easy way to find range frequency. 我将告诉您找到范围频率的简单方法。 You can use the binary search technique to get the answer in O(logn) per query. 您可以使用二进制搜索技术来获取每个查询的O(logn)答案。

For that, use arrays of vector to store the index values of all numbers present in the array and then use lower_bound and upper_bound provided by C++ STL. 为此,使用向量数组存储数组中存在的所有数字的索引值,然后使用C ++ STL提供的lower_bound和upper_bound。

Here is C++ Code: 这是C ++代码:

    #define MAX 1000010

    std::vector<int> v[MAX];

    int main(){

    cin>>n;

    for (int i = 0; i < n; ++i)
    {
        cin>>a;
        v[a].push_back(i);
    }

    int low = 0, high = 0;

    int q; //Number of queries
    cin>>q;

    while(q--)
    {
        int l,u,num;   //l=lower range, u=upper range, num=the number of which we will count frequency
        cin>>l>>u>>num;
        low = lower_bound(v[num].begin(), v[num].end(), l) - v[num].begin();
        high = upper_bound(v[num].begin(), v[num].end(), u) - v[num].begin();
        cout<<(high - low)<<endl;
    }

    return 0;
}

Overall Time Complexity: O(Q*log n) 总时间复杂度: O(Q * log n)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何有效地将数组的一系列值与给定数字相乘? - How do I efficiently multiply a range of values of an array with a given number? 如何在数组中找到特定值的频率? - How do I find the frequency of a specific value in an array? 如何查找给定范围内的整数数甚至设置了位 - How to find number of integers in a given range has even set bits 如何找到给定范围内除以给定数字时具有一定余数的值的数量? - How to find the number of values in a given range that has a certain remainder when divided by a given number? 如何找到数组中除数最多的数字? - How do I find the number with the most divisors in an array? 给定索引i,j(j&gt; = i)如何找到子数组(i,j)的A [j]的频率? - Given index i,j(j>=i) How to find the frequency of a A[j] at a subarray(i,j)? 如何有效地查找数字中的数字加起来为特定数字的范围内的位数 - How do I efficiently find the number of digits within a range in which the digits within the number add up to a specific number 如何确保数字在一定范围内? - How do I ensure a number is within a range? 给定一个由N个数字组成的数组,求出所有长度为R?的序列的数目。 - Given an array of N numbers,find the number of sequences of all lengths having the range of R? 在数组中找到最接近给定数字的数字的 position - Find position of a number in array closest to given number
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM