分块和莫队算法
分块
理解
n个元素分成根号n块,没块都有根号n个元素
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int belong[maxn];//这个数在哪一块
int block;//每块大小
int num;//有多少块
int l[maxn];//块的左边
int r[maxn];//块的右边
int a[maxn];
int n;
int q,Max[maxn];
void build()
{fs
block=sqrt(n);//每块大小
num=n/block;if(n%block) num++;//有多少块
for(int i=1;i<=num;i++)
{
l[i]=(i-1)*block+1;//每一块的左边界
r[i]=i*block;//每一块的右边界
}
r[num]=n;//最后一块单独处理右边
for(int i=1;i<=n;i++)
{
belong[i]=(i-1)/block+1;
}
}
莫队算法
提示
只需要考虑Add和Sub函数,其他几乎就是模板
理解
代码
模板
#include <iostream>
#include <string.h>
#include <cmath>
#include <algorithm>//排序用
using namespace std;
const int maxn = 5e4+5;
const int maxm = maxn;
int a[maxn];//记录数据
int pos [maxn];//记录是数据是第几块
struct Q//记录询问
{
int l,r,k;
}q[maxn];
int res;
int main(int argc,char const *argv[])
{
//n m l r
int n,m;
cin>>n>>m;
//分块
int siz = sqrt(n);
int i;
for(i=1;i<=n;i++)
{
cin>>a[i];
pos[i]=i/siz;
}
//查询
for(i=0;i<m;i++)
{
cin>>q[i].l>>q[i].r;
q[i].k=i;
}
//排序
sort(q,q+m,[](Q x,Q y)
{
return pos[x.l]==pos[y.l]?x.r<y.r:pos[x.l]<pos[y.l];
});
//挪区间
int l=1,r=0;//[l,r]闭区间
for(i=0;i<m;i++)
{
while(q[i].l<l) Add(--l);
while(q[i].r>r) Add(++r);
while (q[i].l>l) Sub(l++);
while(q[i].r<r) Sub[r--];
//记录答案
ans[q[i].k]=res;
}
for(i=0;i<m;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}
实战
P2709 小B的询问