一段区间包含了多少种不同的数字
emmmm有很多种做法 莫队 主席树 线段树....我觉得这题还挺好的
我比较弱就用的树状数组 得离线
关键点是要将右端点r作为关键字 若前面出现过 就将其消掉 转移到当前
for(int i=1;i<=m;++i){ for(int j=nxt;j<=ask[i].r;++j){ if(in[a[j]]) update(in[a[j]],-1); update(j,1),in[a[j]]=j; }
这一坨把它比比划划就能明白了 尽量将其往后挪 因为是离线(语无伦次)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define Max(x,y) (x)>(y)?(x):(y) #define Min(x,y) (x)>(y)?(y):(x) #define ll long long #define rg register const int N=500000+5,M=200000+5,inf=0x3f3f3f3f,P=99999997; int n,m,tree[N<<2],a[N<<1],in[N<<1],ans[N<<1]; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int lowbit(int x){return x&(-x);} void update(int pos,int ad){ while(pos<=n) tree[pos]+=ad,pos+=lowbit(pos); } int query(int pos){ int ans=0; while(pos>0) ans+=tree[pos],pos-=lowbit(pos); return ans; } struct node{int l,r,pos;}ask[N]; bool cmp(node a,node b){return a.r<b.r;} int main(){ // freopen("in.txt","r",stdin); rd(n); for(int i=1;i<=n;++i) rd(a[i]); rd(m); for(int i=1;i<=m;++i) rd(ask[i].l),rd(ask[i].r),ask[i].pos=i; sort(ask+1,ask+1+m,cmp); int nxt=1; for(int i=1;i<=m;++i){ for(int j=nxt;j<=ask[i].r;++j){ if(in[a[j]]) update(in[a[j]],-1); update(j,1),in[a[j]]=j; } ans[ask[i].pos]=query(ask[i].r)-query(ask[i].l-1); nxt=ask[i].r+1; } for(int i=1;i<=m;++i) printf("%d ",ans[i]); return 0; }