HDU

题目链接:Necklace

题意:

  给出一串珠子,每个珠子有它的value,现在给出n(n<=5e4)个珠子的value(1<=value<=1e6),现在给出m(1<=m<=2e5)个询问,每个询问给出l和r,要求[l,r]区间内所有珠子的value(如果有相同value值的珠子则只计算一次这个珠子的值)。

题解:

  刚开始看到这题,遇到区间求和就想到了树状数组。但是如何解决区间内相同value值只能计算一次的问题呢?看了题解后发现可以用离线化解决这个问题,我们可以先把所有的询问保存下来,将询问按右端点从小到大排序,然后将所有有重复的value值只保留最后一个位置的值,其他的value值全都减去。因为区间的右端点保证是从小到大的,而可以发现[l,r]这个区间的值就等于所有数保留最后一个出现的数的和(可以自己验证一下)。这里离散化最大的功能就是保证了我们的操作是从小到大的,这样我们前面的操作就不会影响后面的操作。还有这里是要用long long的不然会爆~@。@#

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAX_N = 1e5+9;
 7 typedef pair<int,int> P;
 8 P q[MAX_N*4];
 9 int q1[MAX_N*4];
10 int vis[MAX_N*10];
11 long long vec[MAX_N];
12 long long res[MAX_N];
13 long long out[MAX_N*4];
14 void add(int x,long long num)
15 {
16     for(;x<MAX_N;x+=(x&-x))
17         res[x] += num;
18 }
19 long long sum(int x)
20 {
21     long long ans = 0;
22     for(;x>0;x-=(x&-x))
23         ans += res[x];
24     return ans;
25 }
26 int main()
27 {
28     int N,M,T;
29     cin>>T;
30     while(T--)
31     {
32         cin>>N;
33         memset(res,0,sizeof(res));
34         memset(vis,0,sizeof(vis));
35         for(int i=1;i<=N;i++)
36         {
37             scanf("%lld",&vec[i]);
38             add(i,vec[i]);
39             if(!vis[vec[i]]) vis[vec[i]] = i;
40         }
41         cin>>M;
42         for(int i=0;i<M;i++)
43         {
44             scanf("%d%d",&q1[i],&q[i].first);
45             q[i].second = i;
46         }
47         sort(q,q+M);
48         int right = 1;
49         for(int i=0;i<M;i++)
50         {
51             for(int j=right;j<=q[i].first;j++)
52             {
53                 if(vis[vec[j]] != j)
54                 {
55                     add(vis[vec[j]],-vec[j]);
56                     vis[vec[j]] = j;
57                 }
58             }
59             right = q[i].first;
60             out[q[i].second] = sum(q[i].first) - sum(q1[q[i].second]-1);
61         }
62         for(int i=0;i<M;i++)
63         {
64             printf("%lld
",out[i]);
65         }
66     }
67     return 0;
68 }
原文地址:https://www.cnblogs.com/doggod/p/8406793.html