num[i]表示在[l,r]内数字i的个数
当区间变为[l±1,r]或,[l,r±1]的时候,num[i]由0变为1或由1变为0时答案才会变化
#include<complex> #include<cstdio> #include<algorithm> using namespace std; const int N=5e4+7; struct node{ int l,r,id; }q[N<<2]; int n,m; int ans[N<<2],a[N],num[N*20],pos[N]; int qread() { int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘)ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x; } bool cmp(const node &a,const node &b) { if(pos[a.l]==pos[b.l])return a.r<b.r; return pos[a.l]<pos[b.l]; } void change(int &tot,int id,int add) { if(add) { if(!num[a[id]]) tot++; num[a[id]]++; return; } num[a[id]]--; if(!num[a[id]])tot--; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) a[i]=qread(); scanf("%d",&m); for(int i=1;i<=m;i++) { q[i].l=qread();q[i].r=qread(); q[i].id=i; } int tmp=sqrt(n); for(int i=1;i<=n;i++) pos[i]=(i-1)/tmp+1; sort(q+1,q+m+1,cmp); int l=1,r=0,tot=0; for(int i=1;i<=m;i++) { while(l<q[i].l) change(tot,l++,0); while(l>q[i].l) change(tot,--l,1); while(r<q[i].r) change(tot,++r,1); while(r>q[i].r) change(tot,r--,0); ans[q[i].id]=tot; } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
也可以用离线算法+树状数组来做这道题
用nxt[i]来记录与第i个数相同的上一个数的位置
将询问的区间按左端点进行排序
用一个指针l指向当前区间的左端点,当l向右移动时,第l个数就不在查询的区间内了,这时就将树状数组中nxt[l]位置上的数+1(自己举个例子就比较好理解了)
#include<complex> #include<cstdio> #include<algorithm> using namespace std; const int N=5e4+7; struct node{ int l,r,id; }q[N<<2]; int n,m; int c[N],nxt[N],pre[N*20],ans[N<<2]; int qread() { int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘)ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x; } inline int Lowbit(int x) { return x&-x; } inline int Add(int x,int v) { for(;x<=n;x+=Lowbit(x)) c[x]+=v; } inline int Sum(int x) { int ans=0; for(;x;x-=Lowbit(x)) ans+=c[x]; return ans; } bool cmp(const node &a,const node &b) { return a.l<b.l; } int main() { scanf("%d",&n); int x; for(int i=1;i<=n;i++) { x=qread(); nxt[pre[x]]=i; if(!pre[x])Add(i,1); pre[x]=i; } scanf("%d",&m); for(int i=1;i<=m;i++) { q[i].l=qread();q[i].r=qread(); q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1; for(int i=1;i<=m;i++) { while(l<q[i].l) { if(nxt[l]) Add(nxt[l],1); l++; } ans[q[i].id]=Sum(q[i].r)-Sum(q[i].l-1); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }