题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1878
离线树状数组,巧妙的思路呢;
给每种项链记录一个最后出现的位置lst,根据项链最后出现是否在区间内来计算种类数;
于是就用树状数组求前缀和来得到结果。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxn=50005,maxm=200005; int n,m,a[maxn],f[maxn],lst[1000005]; struct N{ int l,r,bh,w; }q[maxm]; bool cmp(N x,N y){return x.r<y.r;} bool cmp2(N x,N y){return x.bh<y.bh;} void add(int x,int k) { for(;x<=n;x+=(x&-x))f[x]+=k; } int query(int x) { int ret=0; for(;x;x-=(x&-x))ret+=f[x]; return ret; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); scanf("%d",&m); for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].bh=i; sort(q+1,q+m+1,cmp); int tot=1; for(int i=1;i<=n;i++) { if(lst[a[i]])add(lst[a[i]],-1); lst[a[i]]=i;add(i,1); while(i==q[tot].r)q[tot].w=query(i)-query(q[tot].l-1),tot++; } sort(q+1,q+m+1,cmp2); for(int i=1;i<=m;i++)printf("%d ",q[i].w); return 0; }