码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-07-13 14:06:50      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:hdu 3333 turing tree   树状数组   离线操作   

Turing Tree

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


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 1540 1255 1828 3340 
 


题意:求一个区间内不重复数字的和,例如1 1 1 3,区间[1,4]的和为4。

题解:先把要求的区间按右区间升序排序,再把原来的数组按顺序依次插入树状数组,假设当前插入a[i],

            先判断a[i]在之前有没有出现过,没有的话直接插入add(i,a[i]),记录这个位置;有的话就当前位置

           插入a[i],上一次的位置减去a[i],add(i,a[i]);  add(mp[a[i]],-a[i]);。。然后查询是否有把当前位置作为右

           区间的查询Q,有的话就查询该段区间的和。

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<map>
#include<vector>
#define N 30010
#define M 100010
#define ll long long

using namespace std;

int n,t,q;
int a[N],Rl[N],Rr[N];
map<int,int>mp;///记录上一次出现的位置

struct node {
    int id;
    int l,r;
} Q[M];

ll bit[N],as[M];

bool cmp_1(node a,node b) {
    if(a.r==b.r)return a.l<b.l;
    return a.r<b.r;
}

void add(int i,int v) {
    while(i<=n) {
        bit[i]+=v;
        i+=i&-i;
    }
}

ll getsum(int i) {
    ll s=0;
    while(i>0) {
        s+=bit[i];
        i-=i&-i;
    }
    return s;
}

int main() {
    //freopen("test.in","r",stdin);
    cin>>t;
    while(t--) {
        cin>>n;
        for(int i=1; i<=n; i++)scanf("%d",&a[i]);
        cin>>q;
        for(int i=1; i<=q; i++) {
            scanf("%d%d",&Q[i].l,&Q[i].r);
            Q[i].id=i;
        }
        sort(Q+1,Q+1+q,cmp_1);
        memset(bit,0,sizeof bit);
        memset(Rl,0,sizeof Rl);
        memset(Rr,0,sizeof Rr);
        ///预处理右区间相同的左右区间
        int f=1;
        Rl[Q[f].r]=f;
        Rr[Q[f].r]=f;
        for(int ii=2; ii<=q;) {
            while(Q[f].r==Q[ii].r&&ii<=q)ii++;
            Rl[Q[f].r]=f;
            Rr[Q[f].r]=ii-1;
            f=ii;
        }
        mp.clear();
        for(int i=1; i<=n; i++) {
            ///前面没出现过
            if(!mp[a[i]]) {
                add(i,a[i]);
                mp[a[i]]=i;
            } else {
                ///出现过的话在当前这个位置加上a[i]
                ///在前面出现的位置减去a[i]
                add(i,a[i]);
                add(mp[a[i]],-a[i]);
                mp[a[i]]=i;
            }
            if(!Rl[i])continue;
            int L=Rl[i],R=Rr[i];
            ll ans=getsum(i);
            for(int j=L; j<=R; j++) {
                ll ans_2=ans;
                ans_2-=getsum(Q[j].l-1);
                as[Q[j].id]=ans_2;
            }
        }
        for(int i=1; i<=q; i++) {
            printf("%I64d\n",as[i]);
        }
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:hdu 3333 turing tree   树状数组   离线操作   

原文地址:http://blog.csdn.net/acm_baihuzi/article/details/46861109

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!