风吹夏天 2020-05-01
莫队算法链接:传送门
题意:
有n个数,m个区间。问区间内有多少个x,x满足x的个数等于x的值的个数(如果x是3,区间内要存在3个3)。
题解:
因为a[i]太大,所以要离散化一下,但是不能用map容器,因为map容器多一个log
莫队就是离线问题+区间的移动。复杂度是O((N+M)*√N)
莫队代码还要分块要不然还会TLE,分块大小为sqrt(n)
未分块-TLE代码:
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <set> #include <map> #include <string> #include <queue> #include <stack> #include <string> using namespace std; typedef long long ll; using namespace std; const int maxn=1e5+7; int unit,n,m; struct Node { int l,r,id,result; }node[maxn]; bool mmp1(Node x,Node y) { if(x.l==y.l) return x.r<y.r; return x.l<y.l; } bool mmp2(Node x,Node y) { return x.id<y.id; } int a[maxn],b[maxn],num[maxn],pr[maxn],ans; int add(int i) { num[a[i]]++; if(num[a[i]]==b[a[i]]) ans++; else if(num[a[i]]==b[a[i]]+1) ans--; } void del(int i) { num[a[i]]--; if(num[a[i]]==b[a[i]]) ans++; else if(num[a[i]]==b[a[i]]-1) ans--; } int main() { scanf("%d%d",&n,&m); unit=(int)sqrt(n); for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); int cnt=unique(b+1,b+1+n)-(b+1); for(int i=1;i<=n;++i) { a[i]=lower_bound(b+1,b+1+cnt,a[i])-b; } for(int i=1;i<=m;++i) scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i; sort(node+1,node+1+m,mmp1); int lpos=node[1].l,rpos=lpos-1; for(int i=1;i<=m;++i) { while(lpos>node[i].l) add(--lpos); while(rpos<node[i].r) add(++rpos); while(lpos<node[i].l) del(lpos++); while(rpos>node[i].r) del(rpos--); node[i].result=ans; } sort(node+1,node+1+m,mmp2); for(int i=1;i<=m;++i) printf("%d\n",node[i].result); return 0; }
分块-正确代码:
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <set> #include <map> #include <string> #include <queue> #include <stack> #include <string> using namespace std; typedef long long ll; using namespace std; const int maxn=1e5+7; int unit,n,m; struct Node { int l,r,id,result; bool operator < (const Node x)const { return l/unit==x.l/unit?r<x.r:l<x.l; } }node[maxn]; //bool mmp1(Node x,Node y) //{ // if(x.l==y.l) // return x.r<y.r; // return x.l<y.l; //} bool mmp2(Node x,Node y) { return x.id<y.id; } int a[maxn],b[maxn],num[maxn],pr[maxn],ans; int add(int i) { num[a[i]]++; if(num[a[i]]==b[a[i]]) ans++; else if(num[a[i]]==b[a[i]]+1) ans--; } void del(int i) { num[a[i]]--; if(num[a[i]]==b[a[i]]) ans++; else if(num[a[i]]==b[a[i]]-1) ans--; } int main() { scanf("%d%d",&n,&m); unit=(int)sqrt(n); for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); int cnt=unique(b+1,b+1+n)-(b+1); for(int i=1;i<=n;++i) { a[i]=lower_bound(b+1,b+1+cnt,a[i])-b; } for(int i=1;i<=m;++i) scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i; sort(node+1,node+1+m); int lpos=node[1].l,rpos=lpos-1; for(int i=1;i<=m;++i) { while(lpos>node[i].l) add(--lpos); while(rpos<node[i].r) add(++rpos); while(lpos<node[i].l) del(lpos++); while(rpos>node[i].r) del(rpos--); node[i].result=ans; } sort(node+1,node+1+m,mmp2); for(int i=1;i<=m;++i) printf("%d\n",node[i].result); return 0; }