//思路:1) 首先将询问的区间[L,R]按照R从小到大排序,这样R前面的都小于等于R
// 2) 利用树状数组求解,m_hash{value] = index;表示值value存放在m_hash数组的index位置
// 并且在m_hash数组中index之前的数只出现过一次
// 3) 当我们现在当前的index比R小,则说明从[Index]到R还有数可以继续放到m_hash数组中
// a)若m_hash.find(value) != m_hash.end() 则说明,这个value在index之前已经出现过了,所以我们把它从树状数组中删除
// 同时更新树状数组,把以前的value删掉,以前这个value的index = m_hash[value],然后转到c;
// b)若m_hash(value) == m_hash.end(), 说明value在index之前从来没有出现过,是个新值,我们直接转到c,直接更新树状数组
// c)update(index, value); m_hash[value] = index;index++;
// 注意:由于数组较大,所以使用__int64位;
// 2) 利用树状数组求解,m_hash{value] = index;表示值value存放在m_hash数组的index位置
// 并且在m_hash数组中index之前的数只出现过一次
// 3) 当我们现在当前的index比R小,则说明从[Index]到R还有数可以继续放到m_hash数组中
// a)若m_hash.find(value) != m_hash.end() 则说明,这个value在index之前已经出现过了,所以我们把它从树状数组中删除
// 同时更新树状数组,把以前的value删掉,以前这个value的index = m_hash[value],然后转到c;
// b)若m_hash(value) == m_hash.end(), 说明value在index之前从来没有出现过,是个新值,我们直接转到c,直接更新树状数组
// c)update(index, value); m_hash[value] = index;index++;
// 注意:由于数组较大,所以使用__int64位;
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define NSIZ 50010
#define MSIZ 200010
__int64 tree[NSIZ];
__int64 sum[MSIZ];
typedef struct Node_
{
int x, y;
int index;
}Node;
Node nodes[MSIZ];
int arr[NSIZ];
map<int, int> m_hash;
int cmp(Node a, Node b)
{
if (a.y == b.y)
{
return a.x < b.x;
}
return a.y < b.y;
}
int lowbit(int n)
{
return n&(-n);
}
void udpate(int n, int i, int x)
{
while(i <= n)
{
tree[i] += x;
i += lowbit(i);
}
}
__int64 getsum(int i)
{
__int64 sum = 0;
while(i >= 1)
{
sum += tree[i];
i -= lowbit(i);
}
return sum;
}
int main()
{
int t, i;
int n, a;
int m;
scanf("%d", &t);
int num;
while(t--)
{
scanf("%d", &n);
memset(sum ,0, sizeof(sum));
memset(tree, 0, sizeof(tree));
memset(nodes, 0, sizeof(nodes));
for (i = 1;i <= n; ++i)
{
scanf("%d", &arr[i]);
}
scanf("%d", &m);
for(i = 1;i <= m; ++i)
{
scanf("%d %d", &nodes[i].x, &nodes[i].y);
nodes[i].index = i;
}
sort(nodes + 1, nodes + m + 1, cmp);
m_hash.clear();
num = 1;
for (i = 1;i <= m; ++i)
{
while(num <= nodes[i].y)
{
if(m_hash.find(arr[num]) != m_hash.end())
{
udpate(n, m_hash[arr[num]], -arr[num]);
}
m_hash[arr[num]] = num;
udpate(n, num, arr[num]);
++num;
}
sum[nodes[i].index] = getsum(nodes[i].y) - getsum(nodes[i].x - 1);
}
for(int i=1;i<=m;++i) printf("%I64d\n",sum[i]);
}
return 0;
}

本文介绍了一种利用树状数组实现区间操作优化的算法,通过将询问区间按照R值从小到大排序,并结合哈希表记录每个值首次出现的位置,实现了高效的数据查询与更新。该算法特别适用于需要频繁进行区间查询与更新的场景,如在线编辑系统、实时数据处理等。
6万+

被折叠的 条评论
为什么被折叠?



