hdu 3333 树状数组+离线处理

思路:既然要求的是不同的元素的和,那么我们可以想办法让每个值在区间中只出现一次,于是想到了离线的算法:将查询按照右端点排序,位置在右端点之前的元素都插入到树状数组中,对于已经出现过的值,我们要先删除(在原位置)再插入(在cur的位置),因为很显然对于同一个元素,只有在最靠右的位置出现一次才能返回正确的查询结果。所以我们需要用map来记录每个值上一次插入的位置,删除后再插入到当前位置。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <map>
 6 using namespace std;
 7 
 8 typedef long long ll;
 9 const int N = 30001;
10 const int Q = 100001;
11 ll c[N];
12 ll ans[Q];
13 int a[N];
14 
15 struct Query
16 {
17     int i, j, id;
18     bool operator < ( const Query & o ) const 
19     {
20         return j < o.j;
21     }
22 } query[Q];
23 
24 map<int, int> mp;
25 
26 int lb( int i )
27 {
28     return i & -i;
29 }
30 
31 void update( int i, int v )
32 {
33     while ( i < N )
34     {
35         c[i] += v;
36         i += lb(i);        
37     }
38 }
39 
40 ll get( int i )
41 {
42     ll ans = 0;
43     while ( i )
44     {
45         ans += c[i];
46         i -= lb(i);
47     }
48     return ans;
49 }
50 
51 int main ()
52 {
53     int t;
54     scanf("%d", &t);
55     while ( t-- )
56     {
57         int n, q;        
58         scanf("%d", &n);
59         for ( int i = 1; i <= n; i++ )
60         {
61             scanf("%d", a + i);            
62         }
63         scanf("%d", &q);
64         for ( int i = 1; i <= q; i++ )
65         {
66             scanf("%d%d", &query[i].i, &query[i].j);        
67             query[i].id = i;    
68         }
69         sort( query + 1, query + 1 + q );
70         memset( c, 0, sizeof(c) );
71         mp.clear();
72         int cur = 1;
73         for ( int i = 1; i <= q; i++ )
74         {
75             while ( cur <= query[i].j )
76             {
77                 if ( mp.count(a[cur]) )
78                 {
79                     int pos = mp[a[cur]];
80                     update( pos, -a[cur] );
81                 }
82                 update( cur, a[cur] );
83                 mp[a[cur]] = cur;
84                 cur++;
85             }
86             ans[query[i].id] = get( query[i].j ) - get( query[i].i - 1 );
87         }
88         for ( int i = 1; i <= q; i++ )
89         {
90             printf("%I64d\n", ans[i]);
91         }
92     }
93     return 0;
94 }

 

posted @ 2015-07-29 20:22  hxy_has_been_used  阅读(230)  评论(0编辑  收藏  举报