题目大意:求一个区间内不重复数字的和,例如1 1 1 3,区间[1,4]的和为4。
思路:如果采用在线算法,很难在nlogn的时间内处理,所以考虑离线算法。
首先我们把所有查询区间记录下来,然后按照区间的右值排序,接着从左到右把每一个数更新到线段树中,并记录它出现的位置。
如果一个数已经出现过,那么我们就把他上次出现的位置的值置为0,并更新它出现的位置。
因为我们的查询区间是按右值排序的,所以当前区间的左值要么和之前一样要么比之前的要大,因此把过去重复出现的数字置为0不会影响结果。
当更新到某个区间的右值时,我们就查询一次该区间的答案,并把答案记录到对应的地方。
最后把区间查询的答案按照输入顺序输出即可。
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <set> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <cmath> 10 #include <map> 11 using namespace std; 12 #define INF 0x73737373 13 #define EPS 1e-8 14 #define lson l, m, rt<<1 15 #define rson m+1, r, rt<<1|1 16 #define MAXN 55555 17 __int64 sum[MAXN<<2], A[MAXN], ans[MAXN<<2]; 18 map <__int64, int> hash; 19 struct Query_Node 20 { 21 int l, r, index; 22 friend bool operator < (Query_Node a, Query_Node b) 23 { 24 return a.r < b.r; 25 } 26 }q[MAXN<<2]; 27 void push_up(int rt) 28 { 29 sum[rt] = sum[rt<<1|1] + sum[rt<<1]; 30 } 31 void update(int l, int r, int rt, int p, __int64 val) 32 { 33 if(l == r) 34 { 35 sum[rt] += val; 36 return; 37 } 38 int m = (l + r) >> 1; 39 if(p <= m) update(lson, p, val); 40 else update(rson, p, val); 41 push_up(rt); 42 } 43 __int64 query(int l, int r, int rt, int L, int R) 44 { 45 if(L <= l && R >= r) 46 return sum[rt]; 47 int m = (l + r) >> 1; 48 __int64 ret = 0; 49 if(L <= m) ret += query(lson, L, R); 50 if(R > m) ret += query(rson, L, R); 51 return ret; 52 } 53 int main() 54 { 55 int t; 56 scanf("%d", &t); 57 while(t--) 58 { 59 int n, m; 60 hash.clear(); 61 memset(sum, 0, sizeof(sum)); 62 scanf("%d", &n); 63 for(int i = 1; i <= n; i++) 64 scanf("%I64d", &A[i]); 65 scanf("%d", &m); 66 for(int i = 0; i < m; i++) 67 { 68 scanf("%d%d", &q[i].l, &q[i].r); 69 q[i].index = i; 70 } 71 sort(q, q + m); 72 int pos = 1; 73 for(int i = 0; i < m; i++) 74 { 75 for(;pos <= n && pos <= q[i].r; pos++) 76 { 77 if(hash[A[pos]]) update(1, n, 1, hash[A[pos]], -A[pos]); 78 update(1, n, 1, pos, A[pos]); 79 hash[A[pos]] = pos; 80 } 81 ans[q[i].index] = query(1, n, 1, q[i].l, q[i].r); 82 } 83 for(int i = 0; i < m; i++) 84 printf("%I64d\n", ans[i]); 85 } 86 return 0; 87 }