题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1878
需要离线。
巧妙的树状数组。按 r 递增排序,只让该颜色的最右端贡献1。
还可以用莫队算法。但是没写。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=5e4+5,M=2e5+5,maxn=1e6+5;; int n,m,a[N],last[maxn],tot,f[N]; struct Ques{ int l,r,bh;int ans; }q[M]; bool cmp(Ques a,Ques b){return a.r<b.r;} bool cmp2(Ques a,Ques b){return a.bh<b.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);tot=1; for(int i=1;i<=n;i++) { if(last[a[i]])add(last[a[i]],-1);add(i,1);last[a[i]]=i; while(i==q[tot].r)q[tot].ans=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].ans); return 0; }