天天看點

【HDU - 3333】【Turing Tree】

題目:

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      

題目分析:就是給完咱們每個點的值,在進行詢問 ,每個區間内不同數字的和,看似很簡單的問題,但是卻沒有用線段樹寫過,是以難度有點大,最後參考的題解,明确了解題思路,先把每個區間按右端點排序,在從右向左周遊,如果這個數字第一次出現,就加上,如果再次出現了這個數字,那麼就把之前已經出現的數字删除,将新的數字添上去。

ac代碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100005
using namespace std;
typedef long long ll;

struct node{
	int l,r;
	int s;
}q[maxn];
bool cmp(node a,node b)
{
	return a.r<b.r;
}
ll bi[maxn],num[maxn];
ll c[maxn],ans[maxn];
int last[maxn];
int n;

int lowbit(int x)
{
	return x&-x;
}
void add(int x,int v)
{
	while(x<=n)
	{
		c[x]+=v;
		x+=lowbit(x);	
	}	
} 
ll sum(int i)
{
	ll ret=0;
	while(i>0)
	{
		ret+=c[i];
		i-=lowbit(i);
	}
	return ret;
}

int main()
{
	int t,Q;
	cin>>t;
	while(t--)
	{
		memset(c,0,sizeof(c));
		memset(last,0,sizeof(last));
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%I64d",&num[i]);
			bi[i]=num[i];
		}
		scanf("%d",&Q);
		for(int i=1;i<=Q;i++)
		{
			cin>>q[i].l>>q[i].r;
			q[i].s=i;
		}
		sort(q+1,q+1+Q,cmp);
		sort(bi+1,bi+1+n);
		int k=1;
		for(int i=1;i<=n;i++)
		{
			int pos=lower_bound(bi+1,bi+1+n,num[i])-bi;
			if(!last[pos])
			{
				add(i,num[i]);
				last[pos]=i;
			}
			else
			{
				add(last[pos],-num[i]);
				add(i,num[i]);
				last[pos]=i;
			}
			while(q[k].r==i&&k<=Q)
			{
				ans[q[k].s]=sum(i)-sum(q[k].l-1);
				k++;
			}
		}
		for(int i=1;i<=Q;i++)
		{
			printf("%I64d\n",ans[i]);
		}
	}
	return 0;
}