Turing Tree
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4455 Accepted Submission(s): 1561
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.
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).
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
好像看过出题人的博客 2333333
题意:求出给定区间内不同种类的数的和值。
题解:
求区间啥啥的 八九不离十是线段树,树状数组,这题我们选用树状数组。
为了让区间和能表示我们想要的结果,同一个数只能出现一次,如果再次出现,我们需要把之前出现的删掉,再在当前位置加入。
则这样操作后,保证了当前位置前的区间是处理完的,是符合题意得。所以我们不能按照题给的顺序求区间,此时想到离线操作,我们把每个区间的右端点升序排列(此时操作里还需要一步离散化,因为最后需要按照给定区间的顺序进行输出)每加入数ai,就判断ai前有没有一个完整的区间,如果有,求出这个区间的ans。剩下操作如上面所说。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mem(a) memset(a, 0, sizeof(a))
#define eps 1e-5
#define M 100005
#define N 30010
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
map<int,int> mp;
int t,n,m;
ll rre[M];
ll f[N];
int a[N];
struct node
{
int l,r,id;
bool operator<(const node &n)const{
return r<n.r||(r==n.r&&l<n.l);
}
}qu[M];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
while(x<=n)
{
f[x]+=y;
x+=lowbit(x);
}
}
ll sum(int x)
{
ll ans=0;
while(x>0)
{
ans+=f[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
mem(f);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
qu[i]=(node){x,y,i};
}
sort(qu,qu+m);
int cur=0;
mp.clear();
for(int i=1;i<=n;i++)
{
if(mp.find(a[i])==mp.end())//之前没加入过a[i]这个数。
{
add(i,a[i]);
mp.insert(make_pair(a[i],i));//记录a[I]出现的位置。
}
else
{
add(i,a[i]);
add(mp[a[i]],-a[i]);
mp[a[i]]=i;
}
while(qu[cur].r==i)//判断之前有没有完整区间
{
rre[qu[cur].id]=sum(qu[cur].r)-sum(qu[cur].l-1);
cur++;
}
}
for(int i=0;i<m;i++)
cout<<rre[i]<<endl;
}
return 0;
}