# HDOJ3333 Turing Tree ---- 树状数组离线查询

Problem Description

After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again...

Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.

Input

The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).

Output

For each Query, print the sum of distinct values of the specified subsequence in one line.

Sample Input




2 3 1 1 4 2 1 2 2 3 5 1 1 2 1 3 3 1 5 2 4 3 5

Sample Output




1 5 6 3 6

题意： 输入n个数，给定m组询问l,r，要求查询出l-r区间内去重后的数字和（从1开始数）

题解： 本来是想简单复习下树状数组，切个水题的，本来以为这题很简单，结果写出来一直TLE，一查才发现这题比我想象的难，思路的话就完全参照的https://www.cnblogs.com/CSU3901130321/p/4754259.html ，因为不会这道题，代码基本照着他敲的。。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define MAXN 30010
using namespace std;
typedef long long ll;
ll c[MAXN]; // 存储树状数组
int input[MAXN]; // 输入数组
ll result[100010]; // 保存查询结果
map<int,int> mp;
struct Query {
int l,r,id;
void init(int a,int b,int c) {l = a, r = b,id = c;}
bool operator < (const Query & q) const{
return (r<q.r) || (r==q.r&&l<q.l);
}
}qu[100010];
int n,m; // 输入数的个数
int lowbit(int x) {return x & -x;}
// pos下标处增加x
void update(int pos,int x) {
while(pos <= n) {
c[pos] += x;
pos = pos + lowbit(pos);
}
}
// 查询前x项和
ll query(int x) {
ll cnt = 0;
while(x >= 1) {
cnt += (ll)c[x];
x -= lowbit(x);
}
return cnt;
}

int main()
{
int t;
scanf("%d",&t);
while(t--) {
memset(c,0,sizeof(c));
memset(qu,0,sizeof(qu));
mp.clear();
scanf("%d",&n);
for(int i = 1;i <= n;i++) {
scanf("%d",&input[i]);
}
scanf("%d",&m);
int l,r;
for(int i = 0;i < m;i++) {
scanf("%d%d",&l,&r);
qu[i].init(l,r,i);
}
sort(qu,qu+m);
int cur = 0;// 当前要查询的语句编号
for(int i = 1;i <= n;i++) {
if(mp.count(input[i]) == 0) {
update(i,input[i]);
mp.insert(make_pair(input[i],i));
} else {
update(mp[input[i]],-input[i]);
update(i,input[i]);
mp[input[i]] = i;
}
// 离线查询
while(qu[cur].r == i) {
result[qu[cur].id] = query(qu[cur].r) - query(qu[cur].l-1);
cur++;
}
}
for(int i = 0;i < m;i++) {
printf("%lld\n",result[i]);
}
}

return 0;
} 

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120