hdu 3333(树状数组 + 离散化 + hash)

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

[email protected]

Source

HDOJ Monthly Contest – 2010.03.06

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;
}
时间: 2024-10-08 04:31:45

hdu 3333(树状数组 + 离散化 + hash)的相关文章

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

HDU 1394 树状数组+离散化求逆序数

对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们通过树状数组可以明显提高时间效率. 我们可以按照排列的顺序依次将数字放入树状数组中,并依次更新预与之相关联的树状数组元素.那么在将其更新完毕后,我们知道每个数对应的树状数组元素的左边的数肯定比它小,我们在以序列顺序依次更新树状数组时,如果有值在它前面出现,那么它对应的树状数组元素(在这个题目里存放的

hdu 5792 树状数组+离散化+思维

题目大意: Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ada≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad. A1,A2?AnA1,A2?An.  1≤n≤500001≤n≤50000  0≤Ai≤1e9 基本思路: 最朴素的思想就是算出所有顺序对所有逆序对

Segment Game (hdu 5372 树状数组+离散化)

Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 534    Accepted Submission(s): 132 Problem Description Lillian is a clever girl so that she has lots of fans and often receives gift

[hdu 4417]树状数组+离散化+离线处理

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 把数字离散化,一个查询拆成两个查询,每次查询一个前缀的和.主要问题是这个数组是静态的,如果带修改操作就不能离线了. //http://acm.hdu.edu.cn/showproblem.php?pid=4417 #include<bits/stdc++.h> using namespace std; const int maxn=100005; int tree[maxn]; int N;

hdu 3015 树状数组+离散化

#include <stdio.h> #include <stdlib.h> #include <algorithm> using namespace std; struct data { __int64 order; __int64 orign; __int64 rank; }; data heigh[100100], coor[100100]; int cmp(const void *a, const void *b) { return ( (*(data *)a)

Swaps and Inversions HDU - 6318 树状数组+离散化

#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; typedef long long ll; const int N=1e5+10; int a[N]; int ra[N]; int tr[N]; int n,x,y; int sz; int lowbit(int x) { return x&-x; } void

Turing Tree HDU - 3333 (树状数组,离线求区间元素种类数)

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..

C - The Battle of Chibi HDU - 5542 (树状数组+离散化)

Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about it. He thought the only way to beat Cao Cao is to have a spy in Cao Cao's army. But all generals and soldiers of Cao Cao were loyal, it's impossible t