hdu 3333(树状数组 + 离线操作)

 

Turing Tree

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3847    Accepted Submission(s): 1306


Problem Description
After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again...

Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.
 

 

Input
The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
 

 

Output
For each Query, print the sum of distinct values of the specified subsequence in one line.
 

 

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

 

Sample Output
1 5 6 3 6
 

 

Author
3xian@GDUT
 

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1542 3397 1394 1540 1255 

题目描述: 求给定一个序列中某段子区间的相异数的和。

要求相异数的和,那就把相同的数去掉就行,可是由于查询的区间不确定,假设要查被删数之前包含被删数的区间的和,就不好办了。

所以我们首先读入所有的查询,然后在建立树状数组的过程中可以一次回答以i结尾的数之前的所有查询,如果有重复的就删掉,

因为比i小的以它结尾所有的查询都存下。由于要按顺序输出它的结果,所以我们给每个查询操作编号,又由于要从小到大回答以i结尾

的所有查询,所以我们采用一个结构体,成员变量分别是L,R,ID;以R来对结构体排序,将结果存入map<int,int > s;

s[ID]中,采用二维数组浪费空间,采用map进行映射.

最后一点要注意的是c数组的大小要是n的最大值×4;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
#define maxn 55555*4
#define LL long long
#define inf 0x3f3f3f3f3f3f3f3f3f3f
#define lowbit(x)   x & (-x)
using namespace std;
//int visit[maxn];
//int VISIT[maxn];
map <LL,LL >  visit;
map <LL ,LL > VISIT;
LL  A[maxn];
int n,cnt;
struct node
{
    int L,R,id;
};
node Q[maxn];
LL c[maxn];
LL ans[maxn];
void init()
{
    memset(c,0,sizeof(c));
    //memset(visit,0,sizeof(visit));
     //memset(VISIT,0,sizeof(VISIT));
    visit.clear();
    VISIT.clear();
    cnt=0;
}
LL sum(int x)
{
    LL ret=0;
    while(x>0)
    {
      ret+=c[x];
      x-=(x&(-x) );
    }
    return ret;
}
void add(int x,LL d)
{
   while(x<=n)
   {
      c[x]+=d;
      x+=(x& (-x) );
   }
}
void solve()
{
    for(int i=1;i<=n;i++)
    {
        if(visit[A[i]]!=0)
        {
            add(visit[A[i]],-A[i]);
        }
        visit[A[i]]=i;
        add(i,A[i]);
        if(VISIT[i]!=0)
        {
            for(int j=1;j<=VISIT[i];j++)
            {
                cnt++;
                ans[Q[cnt].id]=sum(Q[cnt].R)-sum(Q[cnt].L-1);
                //printf("%lld\n",ans[Q[cnt].id]);
            }
        }
    }
}
bool cmp(node a,node b)
{
  if(a.R==b.R)
     return a.L<b.L;
   else
    return a.R<b.R;
}
int main()
{
//freopen("test.txt","r",stdin);
    int t,q;
    scanf("%d",&t);
    while(t--)
    {
         init();
         scanf("%d",&n);
         for(int i=1;i<=n;i++)
            scanf("%lld",&A[i]);
         scanf("%d",&q);
         for(int i=1;i<=q;i++)
         {
             scanf("%d%d",&Q[i].L,&Q[i].R);
             Q[i].id=i;
             // printf("%d\n",Q[i].id);
             ++VISIT[Q[i].R];
         }
         sort(Q+1,Q+q+1,cmp);

        /* for(int i=1;i<=q;i++)
         {
            printf("%d\n",Q[i].id);
         }*/
         solve();
         for(int i=1;i<=q;i++)
         {
            printf("%lld\n",ans[i]);
         }

    }
    return 0;
}

 

posted on 2015-05-22 16:47  爱装逼的书呆子  阅读(258)  评论(0编辑  收藏  举报

导航