bzoj1878 [SDOI2009]HH的项链
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。
正解:莫队算法
莫队板子,巨水。。刷了难一点的就觉得这题没有任何难度了。。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf 1<<30 #define il inline #define RG register #define ll long long #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct node{ int l,r,i,bl; }q[200010]; int cnt[1000010],ans[200010],a[200010],n,m,block; il int gi(){ RG int x=0,q=0; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x; } il int cmp(const node &a,const node &b){ return a.bl<b.bl || (a.bl==b.bl && a.r<b.r); } il void work(){ n=gi(); for (RG int i=1;i<=n;++i) a[i]=gi(); block=sqrt(n); m=gi(); for (RG int i=1;i<=m;++i) q[i].l=gi(),q[i].r=gi(),q[i].i=i,q[i].bl=(q[i].l-1)/block+1; sort(q+1,q+m+1,cmp); RG int L=1,R=0,Ans=0; for (RG int i=1;i<=m;++i){ while (L>q[i].l){ L--,cnt[a[L]]++; if (cnt[a[L]]==1) Ans++; } while (R<q[i].r){ R++,cnt[a[R]]++; if (cnt[a[R]]==1) Ans++; } while (L<q[i].l){ cnt[a[L]]--; if (!cnt[a[L]]) Ans--; L++; } while (R>q[i].r){ cnt[a[R]]--; if (!cnt[a[R]]) Ans--; R--; } ans[q[i].i]=Ans; } for (RG int i=1;i<=m;++i) printf("%d\n",ans[i]); return; } int main(){ File("necklace"); work(); return 0; }