HDU3874 /HDU3333 树状数组 区间求不重复数和

Necklace

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4604    Accepted Submission(s): 1581


Problem Description
Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count it once. We define the beautiful value of some interval [x,y] as F(x,y). F(x,y) is calculated as the sum of the beautiful value from the xth ball to the yth ball and the same value is ONLY COUNTED ONCE. For example, if the necklace is 1 1 1 2 3 1, we have F(1,3)=1, F(2,4)=3, F(2,6)=6.

Now Mery thinks the necklace is too long. She plans to take some continuous part of the necklace to build a new one. She wants to know each of the beautiful value of M continuous parts of the necklace. She will give you M intervals [L,R] (1<=L<=R<=N) and you must tell her F(L,R) of them.
 

 

Input
The first line is T(T<=10), representing the number of test cases.
  For each case, the first line is a number N,1 <=N <=50000, indicating the number of the magic balls. The second line contains N non-negative integer numbers not greater 1000000, representing the beautiful value of the N balls. The third line has a number M, 1 <=M <=200000, meaning the nunber of the queries. Each of the next M lines contains L and R, the query.
 

 

Output
For each query, output a line contains an integer number, representing the result of the query.
 

 

Sample Input
2 6 1 2 3 4 3 5 3 1 2 3 5 2 6 6 1 1 1 2 3 5 3 1 1 2 4 3 5
 

 

Sample Output
3 7 14 1 3 6
 

 

Source
题意:
给一串数,若干询问,每次询问一个区间内不重复数字之和。
代码:
 1 /*
 2 把询问的几个区间先存起来,将其按照区间右端点从小到大排序,这样当去掉某一区间内的重复值时就不会
 3 影响其他区间,因为其他区间的右端点要么比他小,要么比他大,比他小的不会受影响(树状数组向上更新)
 4 ,比他大的恰好也要去重。去重时利用map。
 5 */
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<map>
 9 #include<cstring>
10 #include<algorithm>
11 #include<cmath>
12 const int MAXN=50005;
13 const int MAXM=200005;//MAXM,MAXN改为30005,1000005就是HDU3333题题解
14 long long A[MAXN];
15 long long NE[MAXN];
16 int t,n,m;
17 struct Necklace
18 {
19     int R,L,id;//区间右端点,区间左端点,序号
20 }neck[MAXM];
21 bool cmp(Necklace a,Necklace b)
22 {
23     if(a.R==b.R)
24     return a.L<b.L;
25     else return a.R<b.R;
26 }
27 int lowbit(int x)
28 {
29     return x&(-x);
30 }
31 void add(int id,long long c)
32 {
33     while(id<=MAXN)
34     {
35         A[id]+=c;
36         id+=lowbit(id);
37     }
38 }
39 long long sum(int id)
40 {
41     long long s=0;
42     while(id>0)
43     {
44         s+=A[id];
45         id-=lowbit(id);
46     }
47     return s;
48 }
49 using namespace std;
50 int main()
51 {
52     scanf("%d",&t);
53     while(t--)
54     {
55         scanf("%d",&n);
56         for(int i=1;i<=n;i++)
57         scanf("%lld",&NE[i]);
58         scanf("%d",&m);
59         for(int i=0;i<m;i++)
60         {
61             scanf("%d%d",&neck[i].L,&neck[i].R);
62           //  if(neck[i].L>neck[i].R)
63           //  swap(neck[i].L,neck[i].R);
64             neck[i].id=i;
65         }
66         sort(neck,neck+m,cmp);
67         int p=1;
68         map<int,int>mp;
69         long long ans[MAXM];
70         memset(A,0,sizeof(A));
71         for(int i=0;i<m;i++)
72         {
73             while(p<=neck[i].R)//小于等于区间右端点的
74             {
75                 long long x=NE[p];
76                 if(mp[x]!=0)//如果前面出现过此X值就减去旧的加上新的
77                 add(mp[x],-x);
78                 add(p,x);
79                 mp[x]=p;
80                 p++;
81             }
82             ans[neck[i].id]=sum(neck[i].R)-sum(neck[i].L-1);
83         }
84         for(int i=0;i<m;i++)
85         printf("%lld\n",ans[i]);
86     }
87     return 0;
88 }

 

posted @ 2016-09-27 19:43  luckilzy  阅读(563)  评论(0编辑  收藏  举报