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
[email protected]
Source
HDOJ Monthly Contest – 2010.03.06
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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。