HDU 3874 Necklace(树状数组+离线处理)

 

题目大意

 

有一串长度为 n(1≤n50000) 的项链,项链上每块石头都有一个价值,在计算项链上一段连续石头的价值和的时候,相同价值的只计算一次

现在给你 m(1≤m≤200000) 个询问,每个询问要查询一段连续石头 [L, R] (1≤L≤R≤n)的价值和

 

做法分析

 

先把所有的查询保存,然后按照查询区间的右端点由小到大排序,然后离线处理:


对于一个具体的石头的价值 val,由于我们是按照查询的右端点从小到大排序的,我们当然就希望这个价值出现的位置越靠后(编号越大)越好了,这样就能够保证我们在查询一段区间的和的时候不会算漏了,也就是说,只保留每个价值最靠后的那一块石头,不断的向后加石头更新就行了,具体的说就是这样做的:

        每加一块石头(编号是 id),看这个石头的 val 是否出现过,如果没有出现过,直接加进去就行,然后 last[val]=id

        如果出现过,要先把 last[val] 这个位置的值减去 val,然后在更新,接着给 last[val] 更新:last[val]=id

        如果当前的这块石头是某个查询 [L, R] 的右端点,那么,这个时候直接查询 [L, R] 这段区间的和就行

当然,我们也可以把按照左端点从大到小排序,不过这样的话,我们就得倒着扫石头了

 

参考代码

 

HDU 3874
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 typedef __int64 LL;
 9 const int N=50006;
10 
11 struct Node
12 {
13     int L, R, id;
14     inline void init(int a, int b, int c)
15     {
16         L=a, R=b, id=c;
17     }
18 
19     inline bool operator <(const Node &temp) const
20     {
21         if(R==temp.R) return L<temp.L;
22         else return R<temp.R;
23     }
24 } op[200006];
25 int t, n, m, last[1000006], data[N];
26 LL BIT[N];
27 
28 void update(int pos, int val)
29 {
30     for(; pos<N; pos+=pos&(-pos)) BIT[pos]+=val;
31 }
32 
33 LL query(int pos)
34 {
35     LL sum=0;
36     for(; pos>0; pos-=pos&(-pos)) sum+=BIT[pos];
37     return sum;
38 }
39 
40 LL ans[200006];
41 
42 int main()
43 {
44     scanf("%d", &t);
45     for(int ca=1; ca<=t; ca++)
46     {
47         scanf("%d", &n);
48         for(int i=1; i<=n; i++)
49         {
50             scanf("%d", &data[i]);
51             last[data[i]]=-1;
52         }
53         scanf("%d", &m);
54         for(int i=0, a, b; i<m; i++)
55         {
56             scanf("%d%d", &a, &b);
57             if(a>b) swap(a, b);
58             op[i].init(a, b, i);
59         }
60         sort(op, op+m);
61         memset(BIT, 0, sizeof BIT);
62         for(int i=0, u=1; i<m; i++)
63         {
64             for(; u<=op[i].R; u++)
65             {
66                 if(last[data[u]]!=-1) update(last[data[u]], -data[u]);
67                 last[data[u]]=u;
68                 update(u, data[u]);
69             }
70             ans[op[i].id]=query(op[i].R)-query(op[i].L-1);
71         }
72         for(int i=0; i<m; i++) printf("%I64d\n", ans[i]);
73     }
74     return 0;
75 }

 

题目链接 & AC通道

 

HDU 3874 Necklace

 

 

 

posted @ 2013-04-25 13:05  jianzhang.zj  阅读(238)  评论(0编辑  收藏  举报