1878: [SDOI2009]HH的项链
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1673 Solved: 808
[Submit][Status]
Description
HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。
Input
第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
Output
M行,每行一个整数,依次表示询问对应的答案。
Sample Input
6
1 2 3 4 3 5
3
1 2
3 5
2 6
1 2 3 4 3 5
3
1 2
3 5
2 6
Sample Output
2
2
4
2
4
HINT
对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;
对于100%的数据,N ≤ 50000,M ≤ 200000。
Source
题解:
这题以前做树状数组的时候做过,只不过现在早把思想忘了,今天再来做一下。
巧妙的运用了前缀和,使得树状数组发挥作用。
这题树状数组有两种写法,具体见代码:
1.按右端点排序
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #define inf 1000000000 12 #define maxn 50000+1000 13 #define maxm 200000+10000 14 #define maxk 1000000+1000 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 using namespace std; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 struct rec{int x,y,id;}a[maxm]; 27 int s[maxn],ans[maxm],next[maxn],head[maxk],n,m; 28 void add(int x,int y) 29 { 30 for(;x<=n;x+=x&(-x))s[x]+=y; 31 } 32 int sum(int x) 33 { 34 int t=0; 35 for(;x;x-=x&(-x))t+=s[x]; 36 return t; 37 } 38 bool cmp(rec a,rec b) 39 { 40 return a.y<b.y; 41 } 42 int main() 43 { 44 freopen("input.txt","r",stdin); 45 freopen("output.txt","w",stdout); 46 n=read(); 47 for(int i=1;i<=n;i++) 48 { 49 int x=read(); 50 next[i]=head[x]; 51 head[x]=i; 52 } 53 m=read(); 54 for(int i=1;i<=m;i++) 55 a[i].x=read(),a[i].y=read(),a[i].id=i; 56 sort(a+1,a+m+1,cmp); 57 int now=0; 58 for(int i=1;i<=m;i++) 59 { 60 while(now<a[i].y) 61 { 62 now++; 63 add(next[now]+1,1); 64 add(now+1,-1); 65 } 66 ans[a[i].id]=sum(a[i].x); 67 } 68 for(int i=1;i<=m;i++)printf("%d\n",ans[i]); 69 return 0; 70 }
2.按左端点排序
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #define inf 1000000000 12 #define maxn 50000+1000 13 #define maxm 200000+10000 14 #define maxk 1000000+1000 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 using namespace std; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 struct rec{int x,y,id;}a[maxm]; 27 int s[maxn],ans[maxm],next[maxn],head[maxk],n,m,mx,b[maxn]; 28 void add(int x,int y) 29 { 30 for(;x<=n;x+=x&(-x))s[x]+=y; 31 } 32 int sum(int x) 33 { 34 int t=0; 35 for(;x;x-=x&(-x))t+=s[x]; 36 return t; 37 } 38 bool cmp(rec a,rec b) 39 { 40 return a.x==b.x?a.y<b.y:a.x<b.x; 41 } 42 int main() 43 { 44 freopen("input.txt","r",stdin); 45 freopen("output.txt","w",stdout); 46 n=read(); 47 for(int i=1;i<=n;i++)b[i]=read(); 48 for(int i=n;i>=1;i--) 49 { 50 next[i]=head[b[i]]; 51 head[b[i]]=i; 52 mx=max(mx,b[i]); 53 } 54 m=read(); 55 for(int i=1;i<=m;i++) 56 a[i].x=read(),a[i].y=read(),a[i].id=i; 57 sort(a+1,a+m+1,cmp); 58 for(int i=1;i<=mx;i++)if(head[i])add(head[i],1); 59 int now=1; 60 for(int i=1;i<=m;i++) 61 { 62 while(now<a[i].x) 63 { 64 if(next[now])add(next[now],1); 65 now++; 66 } 67 ans[a[i].id]=sum(a[i].y)-sum(a[i].x-1); 68 } 69 for(int i=1;i<=m;i++)printf("%d\n",ans[i]); 70 return 0; 71 }