牛客网暑期ACM多校训练营(第一场)- J Different Integers (莫队)
题意:裸的莫队题,每个查询Li,Ri,返回区间[1,Li]和[Ri,N]区间中不同的数的个数。
分析:正常的离线查询,是求区间[Li,Ri]中要求的答案,而该题所求答案为外侧两个区间中的答案,那么cnt[i]维护的东西修改一下即可。对查询排序的时候,将R较大的排在前面,因为对于所维护的区间,是从两侧往内递推过来的,这样才能令不必要的递推减少。
此外,也有用主席树和树状数组的做法。
#include<bits/stdc++.h> using namespace std; const int maxn =1e5+5; int pos[maxn]; struct Query{ int L,R,id; bool operator <(const Query q) const{ if(pos[L]==pos[q.L]) return R>q.R; return pos[L]<pos[q.L]; } }Q[maxn]; int a[maxn]; int ans[maxn]; int block; int cnt[maxn]; int vis[maxn]; int res; //区间是相反的 void add(int pos) { cnt[a[pos]]++; if(cnt[a[pos]]==1) res++; } void pop(int pos){ cnt[a[pos]]--; if(cnt[a[pos]]==0) res--; } int main() { int n,q; while(scanf("%d%d",&n,&q)==2){ memset(cnt,0,sizeof(cnt)); block =ceil(sqrt(1.0*n)); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); pos[i] = i/block; } for(int i=1;i<=q;++i){ scanf("%d%d",&Q[i].L,&Q[i].R); Q[i].id = i; } sort(Q+1,Q+q+1); int curL=0,curR=n+1; res=0; for(int i=1;i<=q;++i){ //外区间缩 while(curL>Q[i].L) pop(curL--); while(curR<Q[i].R) pop(curR++); //外区间扩 while(curL<Q[i].L) add(++curL); while(curR>Q[i].R) add(--curR); ans[Q[i].id] = res; } for(int i=1;i<=q;++i){ printf("%d\n",ans[i]); } } }
为了更好的明天