题面:
思路:
就是一道莫队的模板题目......
开一个1000000的数组记录每个数出现的次数,然后每次从1到0或者从0到1更新答案
莫队讲解看这里:莫队
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 inline int read(){ 8 int re=0,flag=1;char ch=getchar(); 9 while(ch>'9'||ch<'0'){ 10 if(ch=='-') flag=-1; 11 ch=getchar(); 12 } 13 while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); 14 return re*flag; 15 } 16 int n,m,cnt[1000010],tot=0,x[50010],curl,curr,block,ans[200010]; 17 struct query{ 18 int l,r,i; 19 }a[200010]; 20 bool cmp(query l,query r){ 21 if(l.l/block!=r.l/block) return (l.l/block)<(r.l/block); 22 else return l.r<r.r; 23 } 24 void add(int i){ 25 cnt[x[i]]++;if(cnt[x[i]]==1) tot++; 26 //cout<<"add "<<i<<" "<<x[i]<<" "<<cnt[x[i]]<<" "; 27 } 28 void erase(int i){ 29 cnt[x[i]]--;if(!cnt[x[i]]) tot--; 30 //cout<<"erase "<<i<<" "<<x[i]<<" "<<cnt[x[i]]<<" "; 31 } 32 int main(){ 33 //freopen("diff.in","r",stdin); 34 //freopen("diff.out","w",stdout); 35 int i; 36 n=read();for(i=1;i<=n;i++) x[i]=read();block=sqrt(n); 37 //cout<<"input one complete "<<n<<" "<<i<<" "; 38 m=read();for(i=1;i<=m;i++) a[i].l=read(),a[i].r=read(),a[i].i=i; 39 //cout<<"input two complete "<<m<<" "<<i<<" "; 40 sort(a+1,a+m+1,cmp);curl=a[1].l;curr=a[1].r; 41 for(i=a[1].l;i<=a[1].r;i++) add(i); 42 ans[a[1].i]=tot; 43 for(i=2;i<=m;i++){ 44 while(curl<a[i].l) erase(curl++); 45 while(curl>a[i].l) add(--curl); 46 while(curr<a[i].r) add(++curr); 47 while(curr>a[i].r) erase(curr--); 48 ans[a[i].i]=tot; 49 //cout<<"now "<<curl<<" "<<curr<<" "; 50 } 51 for(i=1;i<=m;i++) printf("%d ",ans[i]); 52 } 53