分块和莫队算法

分块

理解

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的询问


posted @ 2021-08-23 10:12  kingwzun  阅读(52)  评论(0编辑  收藏  举报