hdu 3333(树状数组 + 离线操作)
Turing Tree
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3847 Accepted Submission(s): 1306
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
3xian@GDUT
Source
Recommend
题目描述: 求给定一个序列中某段子区间的相异数的和。
要求相异数的和,那就把相同的数去掉就行,可是由于查询的区间不确定,假设要查被删数之前包含被删数的区间的和,就不好办了。
所以我们首先读入所有的查询,然后在建立树状数组的过程中可以一次回答以i结尾的数之前的所有查询,如果有重复的就删掉,
因为比i小的以它结尾所有的查询都存下。由于要按顺序输出它的结果,所以我们给每个查询操作编号,又由于要从小到大回答以i结尾
的所有查询,所以我们采用一个结构体,成员变量分别是L,R,ID;以R来对结构体排序,将结果存入map<int,int > s;
s[ID]中,采用二维数组浪费空间,采用map进行映射.
最后一点要注意的是c数组的大小要是n的最大值×4;
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #include <map> #define maxn 55555*4 #define LL long long #define inf 0x3f3f3f3f3f3f3f3f3f3f #define lowbit(x) x & (-x) using namespace std; //int visit[maxn]; //int VISIT[maxn]; map <LL,LL > visit; map <LL ,LL > VISIT; LL A[maxn]; int n,cnt; struct node { int L,R,id; }; node Q[maxn]; LL c[maxn]; LL ans[maxn]; void init() { memset(c,0,sizeof(c)); //memset(visit,0,sizeof(visit)); //memset(VISIT,0,sizeof(VISIT)); visit.clear(); VISIT.clear(); cnt=0; } LL sum(int x) { LL ret=0; while(x>0) { ret+=c[x]; x-=(x&(-x) ); } return ret; } void add(int x,LL d) { while(x<=n) { c[x]+=d; x+=(x& (-x) ); } } void solve() { for(int i=1;i<=n;i++) { if(visit[A[i]]!=0) { add(visit[A[i]],-A[i]); } visit[A[i]]=i; add(i,A[i]); if(VISIT[i]!=0) { for(int j=1;j<=VISIT[i];j++) { cnt++; ans[Q[cnt].id]=sum(Q[cnt].R)-sum(Q[cnt].L-1); //printf("%lld\n",ans[Q[cnt].id]); } } } } bool cmp(node a,node b) { if(a.R==b.R) return a.L<b.L; else return a.R<b.R; } int main() { //freopen("test.txt","r",stdin); int t,q; scanf("%d",&t); while(t--) { init(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&A[i]); scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%d%d",&Q[i].L,&Q[i].R); Q[i].id=i; // printf("%d\n",Q[i].id); ++VISIT[Q[i].R]; } sort(Q+1,Q+q+1,cmp); /* for(int i=1;i<=q;i++) { printf("%d\n",Q[i].id); }*/ solve(); for(int i=1;i<=q;i++) { printf("%lld\n",ans[i]); } } return 0; }