风吹夏天 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;
}