Algorithm 数组在给定范围内每个不同整数的出现次数

Algorithm 数组在给定范围内每个不同整数的出现次数,algorithm,segment-tree,Algorithm,Segment Tree,给定一个由n个整数组成的数组(n=l,end b=query(2*node,l,r,start,mid); ans.insert(ans.end(),b.begin(),b.end()); b=查询(2*节点+1,l,r,中间+1,结束); ans.insert(ans.end(),b.begin(),b.end()); 返回ans; } 您可以使用如上所述的二叉索引树。与其在节点中存储范围和,不如存储各个范围的值到计数的映射 现在,使用输入x查询树,以查找表示相应索引前缀[1..i]中每个元素

给定一个由n个整数组成的数组
(n=l,end b=query(2*node,l,r,start,mid);
ans.insert(ans.end(),b.begin(),b.end());
b=查询(2*节点+1,l,r,中间+1,结束);
ans.insert(ans.end(),b.begin(),b.end());
返回ans;
}

您可以使用如上所述的二叉索引树。与其在节点中存储范围和,不如存储各个范围的值到计数的映射

现在,使用输入
x
查询树,以查找表示相应索引前缀
[1..i]
中每个元素出现频率的映射。这将需要合并O(logn)映射

现在你可以做两个查询:一个查询
l-1
,另一个查询
r
“从后一个结果映射中减去”前一个结果映射。映射减法是按条目进行的。我会让你计算出细节


每个查询的时间为O(k log n)其中k是映射大小。这最多是输入数组中不同元素的数量。

听起来这可能是我们安排查询的候选方法。假设查询的数量和输入的长度都在
n
的顺序上,类似地,我们可以根据
楼层(l/sqrt(n))对它们进行存储
并按
r
对每个桶进行排序。现在我们有了
sqrt(n)

每个bucket的
q
查询最多会有
O(q*sqrt(n))
由于
l
中的每次移动而产生的变化,最多会有
O(n)
由于
r
中的逐渐变化而产生的变化(因为我们按照
r
对每个bucket进行排序,所以在处理bucket时,间隔的这一侧只会稳步增加)

处理一个bucket中所有间隔右侧的更改绑定为
O(n)
,我们有
sqrt(n)
bucket,因此右侧为
O(n*sqrt(n)
。由于所有
q
s的数量为
O(n)
(假设),并且每个bucket最多需要
O(sqrt(n))
左侧的更改,左侧的更改也是
O(n*sqrt(n))


因此,总的时间复杂度将是
O(n*sqrt(n)+k)
,其中
k
是输出的总数。(更新的数据结构可以是一个hashmap,它也允许在其当前存储上进行迭代。)

您可以使用hashmap。从l到r进行迭代,并将每个元素存储为键,将每个元素存储为计数。这将需要O(n)指定给定范围内不同元素计数的数目。每次将元素插入哈希映射时,必须检查哈希映射中是否存在元素。如果元素已存在,则更新计数,否则将计数保留为1。

是否尝试使用段树或二元索引树?我尝试使用段树,但我能想到的最好的方法是给定范围内不同整数的计数,而不是给定范围内每个不同整数的计数。是否有与原始问题相关的链接?分别是1e6和1e9、10e6和10e9?有多少查询?是否可以在线回答查询?因为在代码强制和所有“解决方案几乎做到了你想说的一切。@FarhanTahir我不知道我们如何在在线查询中使用这种方法。但是,codeforces是否存在提前显示所有查询的问题?(这里有讨论。)是的,但我需要在线解决查询。现在我正在尝试构建一个以无序映射为节点的分段树。我猜它可能超过了内存限制。我用分段树代码编辑了这个问题。你能想出什么办法来降低其复杂性吗?可能是通过使用延迟传播?@FarhanTahir我会在问题描述中添加至少,您需要在线回答查询。这似乎是一个重要的细节。您认为我在我首先编写的python代码中做了什么?您做了与我所说的相同的事情,很抱歉我没有仔细查看。我将尝试找到更好的方法。谢谢。
d={}
for i in range(l, r+1):
    if arr[i] not in d:
        d[arr[i]]=0
    d[arr[i]]+=1
Array is [1, 1, 2, 3, 1, 2, 1]

Query 1: l=0, r=6, Output: 4, 2, 3 (4 for 4 1's, 2, for 2 2's and 1 for 1 3)
Query 2: l=3, r=5, Output: 1, 1, 1
const ll N = 1e6+5;
ll arr[N];
unordered_map< ll, ll > tree[4 * N];
int n, q;

void build (ll node = 1, ll start = 1, ll end = n) {
    if (start == end) {
        tree[node][arr[start]] = 1;
        return;
    }
    ll mid = (start + end) / 2;
    build (2 * node, start, mid);
    build (2 * node + 1, mid + 1, end);
    for (auto& p : tree[2 * node]) {
        ll x = p.ff;
        ll y = p.ss;
        tree[node][x] += y;
    }
    for (auto& p : tree[2 * node + 1]) {
        ll x = p.ff;
        ll y = p.ss;
        tree[node][x] += y;
    }
}

vector< ll > query (ll node, ll l, ll r, ll start = 1, ll end = n) {
    vector< ll > ans;
    if (end < l or start > r) return ans;
    if (start >= l and end <= r) {
        for (auto p : tree[node]) {
            ans.push_back (p.ss);
        }
        return ans;
    }
    ll mid = (start + end) / 2;
    vector< ll > b = query (2 * node, l, r, start, mid);
    ans.insert (ans.end (), b.begin (), b.end ());
    b = query (2 * node + 1, l, r, mid + 1, end);
    ans.insert (ans.end (), b.begin (), b.end ());
    return ans;
}