洛谷 P1972 [SDOI2009]HH的项链
题目描述
HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
输入格式:
第一行:一个整数N,表示项链的长度。
第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。
第三行:一个整数M,表示HH 询问的个数。
接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
输出格式:
M 行,每行一个整数,依次表示询问对应的答案。
说明
对于100%的数据,N <= 500000,M <= 200000。
题解:
莫队算法入门题之一。
不赘述,(见我的博客小Z的袜子)
哪位 dalao 能帮我看看下面的代码怎么优化?洛谷上 T 掉了2个点, BZOJ 上也 T 掉了。感谢了!!!
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=500005,M=200005; 4 int n,m,block,col[N],belong[N],ans[M],sum,num[N*2]; 5 struct node{ 6 int l,r,id; 7 }q[M]; 8 inline int read() 9 { 10 int x=0,f=1; char ch=getchar(); 11 while (!isdigit(ch)) 12 f=(ch=='-')?-f:f,ch=getchar(); 13 while (isdigit(ch)) 14 x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 bool cmp(node a,node b) 18 { 19 return belong[a.l]==belong[b.l]?(belong[a.r]==belong[b.r]?a.id<b.id:a.r<b.r):a.l<b.l; 20 } 21 void revise(int x,int w) 22 { 23 num[col[x]]+=w; 24 if (w>0) sum+=(num[col[x]]==1); 25 if (w<0) sum-=(num[col[x]]==0); 26 } 27 int main() 28 { 29 n=read(); 30 block=sqrt(n); 31 for (int i=1; i<=n; i++) 32 { 33 scanf("%d",&col[i]); 34 belong[i]=i/block+1; 35 } 36 m=read(); 37 for (int i=1; i<=m; i++) 38 { 39 int x,y; 40 x=read(),y=read(); 41 q[i].l=x,q[i].r=y,q[i].id=i; 42 } 43 sort(q+1,q+1+m,cmp); 44 int zl=0,zr=0; 45 memset(num,0,sizeof(num)); sum=0; 46 for (int i=1; i<=m; i++) 47 { 48 while (zl<q[i].l) revise(zl,-1),zl++; 49 while (zl>q[i].l) revise(zl-1,1),zl--; 50 while (zr<q[i].r) revise(zr+1,1),zr++; 51 while (zr>q[i].r) revise(zr,-1),zr--; 52 ans[q[i].id]=sum; 53 } 54 for (int i=1; i<=m; i++) 55 printf("%d\n",ans[i]); 56 return 0; 57 }
加油加油加油!!! fighting fighting fighting !!!