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
【题意】给出n个数,然后提出m个问题,求区间内不重复的数之和。
【思路】先按查询的右坐标升序排列(保证我查询的改动不会影响到后面查询的结果)。把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。
线段树:
#include<iostream> #include<stdio.h> #include<map> #include<string.h> #include<algorithm> using namespace std; typedef long long int LL; const int N=300000+10; const int M=100000+10; int n,m; struct node1 { int l,r; LL num; }sum[N*4]; struct node { int ll,rr,index; }q[M]; bool cmp(node x,node y)//按他的右边界排序 { return x.rr<y.rr; } LL a[N]; map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置 LL ans[M]; void build(int k,int l,int r)//建树 { sum[k].l=l; sum[k].r=r; sum[k].num=0; if(l==r) return ; int mid=l+r>>1; build(k*2,l,mid); build(k*2+1,mid+1,r); } void update(int k,int l,int r,int x,LL v)//更新结点的值 { if(l==r) { sum[k].num+=v; return ; } int mid=l+r>>1; if(x<=mid) update(k*2,l,mid,x,v); else update(k*2+1,mid+1,r,x,v); sum[k].num=sum[k*2].num+sum[k*2+1].num; } LL query(int k,int l,int r,int ll,int rr)//查询区间的值 { if(l>=ll&&r<=rr) { return sum[k].num; } int mid=l+r>>1; LL res=0; if(ll<=mid) res+=query(k*2,l,mid,ll,rr); if(rr>mid) res+=query(k*2+1,mid+1,r,ll,rr); return res; } int main() { int t; scanf("%d",&t); while(t--) { mp.clear(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); } build(1,1,n); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d",&q[i].ll,&q[i].rr); q[i].index=i; } sort(q,q+m,cmp); int k=1; for(int i=0;i<m;i++) { for(;k<=q[i].rr;k++) { if(mp[a[k]]!=0) update(1,1,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去 mp[a[k]]=k;//将位置赋给当前的结点 update(1,1,n,k,a[k]);//将当前结点更新到树中 } ans[q[i].index]=query(1,1,n,q[i].ll,q[i].rr); } for(int i=0;i<m;i++) printf("%I64d ",ans[i]); } return 0; }
树状数组:
#include<iostream> #include<stdio.h> #include<string.h> #include<map> #include<algorithm> using namespace std; const int N=30000+10; int n,m,a[N]; long long sum[N*4],ans[N*4]; map<int,int >mp; struct node { int l,r,id; bool operator<(const node &a)const{ if(r==a.r) return l<a.l; return r<a.r; } }q[N*4]; int lowbit(int x) { return x&(-x); } void update(int p,int v) { while(p<=n) { sum[p]+=v; p+=lowbit(p); } } long long int query(int p) { long long int res=0; while(p) { res+=sum[p]; p-=lowbit(p); } return res; } int main() { int t; scanf("%d",&t); while(t--) { mp.clear(); memset(sum,0,sizeof(sum)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } scanf("%d",&m); for(int i=0;i<m;i++) { int l,r; scanf("%d%d",&l,&r); q[i].l=l;q[i].r=r;q[i].id=i; } sort(q,q+m); int cnt=0; for(int i=1;i<=n;i++) { if(mp.find(a[i])==mp.end())//在mp中没有找到 { update(i,a[i]); mp[a[i]]=i; } else { update(i,a[i]); update(mp[a[i]],-a[i]); mp[a[i]]=i; } while(q[cnt].r==i) { ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-1); cnt++; } } for(int i=0;i<m;i++) printf("%lld ",ans[i]); } return 0; }