【发布时间】:2019-06-14 20:53:39
【问题描述】:
给定一个包含 n 个整数的数组(n <= 1e6) [a0, a1, a2, ... an-1] (a[i] <= 1e9) 和多个查询。在每个查询 2 整数 l 和 r (0 <= l <= r <= n-1) 中,我们需要返回此范围内每个不同整数的计数(l 和 r 包括在内)。
我只能想出一个蛮力解决方案来遍历每个查询的完整范围。
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;
}
【问题讨论】:
-
你试过使用分段树还是二叉索引树?
-
-
有原始问题的链接吗?
-
分别是1e6和1e9、10e6和10e9吗?
-
多少查询?