莫队
- 分块:将整个数列按照一定的块大小进行划分,一般块的大小为 \(\sqrt{n}\),其中\(n\)是数列的长度。这样可以将数列分成若干个小块,每个小块内部的元素具有一定的连续性。
- 排序查询区间:对于给定的多个查询区间,按照一定的规则进行排序。通常的排序规则是先按照左端点所在的块进行排序,如果左端点在同一个块内,则按照右端点进行排序。这种排序方式可以使得在处理查询时,相邻的查询区间之间的转移更加高效。
- 区间转移:在处理每个查询区间时,根据当前已经处理过的区间和待处理的区间之间的差异,通过适当的操作来更新统计信息。当从区间转移到时,只需要增加或减少元素对统计结果的影响。
板子
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
struct node
{
int id,l,r;
}q[N];
int n,m;
int cnt[N],sum;
int a[N],ans[N];
bool cmp(node A,node B)
{
if(A.l/sqrt(n)!=B.l/sqrt(N))
return A.l<B.l;
return A.r<B.r;
}
void add(int x)
{
if(!cnt[x]) sum++;
cnt[x]++;
}
void del(int x)
{
cnt[x]--;
if(!cnt[x]) sum--;
}
int main()
{
/*...*/
for(int i=1;i<=m;i++)
{
cin>>q[i].l>>q[i].r;
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
for(int i=1,l=1,r=0;i<=m;++i){
while(l>q[i].l) add(a[--l]);//左扩展
while(r<q[i].r) add(a[++r]);//右扩展
while(l<q[i].l) del(a[l++]);//左删除
while(r>q[i].r) del(a[r--]);//右删除
ans[q[i].id]=sum;
}
return 0;
}
本文来自博客园,作者:流氓兔LMT,转载请注明原文链接:https://www.cnblogs.com/-include-lmt/p/18742626

浙公网安备 33010602011771号