CodeForces - 220B 离散化+莫队算法
Posted kongbursi-2292702937
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 220B 离散化+莫队算法相关的知识,希望对你有一定的参考价值。
莫队算法链接:传送门
题意:
有n个数,m个区间。问区间内有多少个x,x满足x的个数等于x的值的个数(如果x是3,区间内要存在3个3)。
题解:
因为a[i]太大,所以要离散化一下,但是不能用map容器,因为map容器多一个log
莫队就是离线问题+区间的移动。复杂度是O((N+M)*√N)
莫队代码还要分块要不然还会TLE,分块大小为sqrt(n)
未分块-TLE代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <string> 10 #include <queue> 11 #include <stack> 12 #include <string> 13 using namespace std; 14 typedef long long ll; 15 using namespace std; 16 const int maxn=1e5+7; 17 int unit,n,m; 18 struct Node 19 { 20 int l,r,id,result; 21 }node[maxn]; 22 bool mmp1(Node x,Node y) 23 { 24 if(x.l==y.l) 25 return x.r<y.r; 26 return x.l<y.l; 27 } 28 bool mmp2(Node x,Node y) 29 { 30 return x.id<y.id; 31 } 32 int a[maxn],b[maxn],num[maxn],pr[maxn],ans; 33 int add(int i) 34 { 35 num[a[i]]++; 36 if(num[a[i]]==b[a[i]]) ans++; 37 else if(num[a[i]]==b[a[i]]+1) ans--; 38 } 39 void del(int i) 40 { 41 num[a[i]]--; 42 if(num[a[i]]==b[a[i]]) ans++; 43 else if(num[a[i]]==b[a[i]]-1) ans--; 44 } 45 int main() 46 { 47 scanf("%d%d",&n,&m); 48 unit=(int)sqrt(n); 49 for(int i=1;i<=n;++i) 50 scanf("%d",&a[i]),b[i]=a[i]; 51 sort(b+1,b+n+1); 52 int cnt=unique(b+1,b+1+n)-(b+1); 53 for(int i=1;i<=n;++i) 54 { 55 a[i]=lower_bound(b+1,b+1+cnt,a[i])-b; 56 } 57 for(int i=1;i<=m;++i) 58 scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i; 59 sort(node+1,node+1+m,mmp1); 60 int lpos=node[1].l,rpos=lpos-1; 61 for(int i=1;i<=m;++i) 62 { 63 while(lpos>node[i].l) add(--lpos); 64 while(rpos<node[i].r) add(++rpos); 65 while(lpos<node[i].l) del(lpos++); 66 while(rpos>node[i].r) del(rpos--); 67 node[i].result=ans; 68 } 69 sort(node+1,node+1+m,mmp2); 70 for(int i=1;i<=m;++i) 71 printf("%d ",node[i].result); 72 return 0; 73 }
分块-正确代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <set> 8 #include <map> 9 #include <string> 10 #include <queue> 11 #include <stack> 12 #include <string> 13 using namespace std; 14 typedef long long ll; 15 using namespace std; 16 const int maxn=1e5+7; 17 int unit,n,m; 18 struct Node 19 { 20 int l,r,id,result; 21 bool operator < (const Node x)const 22 { 23 return l/unit==x.l/unit?r<x.r:l<x.l; 24 } 25 }node[maxn]; 26 //bool mmp1(Node x,Node y) 27 //{ 28 // if(x.l==y.l) 29 // return x.r<y.r; 30 // return x.l<y.l; 31 //} 32 bool mmp2(Node x,Node y) 33 { 34 return x.id<y.id; 35 } 36 int a[maxn],b[maxn],num[maxn],pr[maxn],ans; 37 int add(int i) 38 { 39 num[a[i]]++; 40 if(num[a[i]]==b[a[i]]) ans++; 41 else if(num[a[i]]==b[a[i]]+1) ans--; 42 } 43 void del(int i) 44 { 45 num[a[i]]--; 46 if(num[a[i]]==b[a[i]]) ans++; 47 else if(num[a[i]]==b[a[i]]-1) ans--; 48 } 49 int main() 50 { 51 scanf("%d%d",&n,&m); 52 unit=(int)sqrt(n); 53 for(int i=1;i<=n;++i) 54 scanf("%d",&a[i]),b[i]=a[i]; 55 sort(b+1,b+n+1); 56 int cnt=unique(b+1,b+1+n)-(b+1); 57 for(int i=1;i<=n;++i) 58 { 59 a[i]=lower_bound(b+1,b+1+cnt,a[i])-b; 60 } 61 for(int i=1;i<=m;++i) 62 scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i; 63 sort(node+1,node+1+m); 64 int lpos=node[1].l,rpos=lpos-1; 65 for(int i=1;i<=m;++i) 66 { 67 while(lpos>node[i].l) add(--lpos); 68 while(rpos<node[i].r) add(++rpos); 69 while(lpos<node[i].l) del(lpos++); 70 while(rpos>node[i].r) del(rpos--); 71 node[i].result=ans; 72 } 73 sort(node+1,node+1+m,mmp2); 74 for(int i=1;i<=m;++i) 75 printf("%d ",node[i].result); 76 return 0; 77 }
以上是关于CodeForces - 220B 离散化+莫队算法的主要内容,如果未能解决你的问题,请参考以下文章
Chika and Friendly Pairs(莫队+离散化+树状数组)
Codeforces 220B - Little Elephant and Array 离线树状数组
『题解』Codeforces220B Little Elephant and Array
BZOJ 3289 Mato的文件管理(莫队+离散化求逆序数)