Algorithm 数组在给定范围内每个不同整数的出现次数
给定一个由n个整数组成的数组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=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;
}