分块莫队

分块

分块分的形式灵活,每一个块里可以是很多东西

eg:https://www.luogu.com.cn/problem/CF455D

需要灵活维护位置的移动,用双端队列就可以搞定。但是细节比较多,【1】同一块和多块的查询/修改是要分开讨论【2】注意及时pop掉元素

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define rint register int 
#define ll long long
#define ull unsigned long long
#define chu printf
inline ll re()
{
    ll x=0,h=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1e5+10,M=sqrt(1e5)+10;
int n,a[N],block,dcc,cnt[M][N],L[M],R[M],bl[N];
deque<int>code[M],tmp;//妙妙妙!
int q,lastans;
inline void change(int l,int r)
{
  //  chu("change:%d-%d\n",l,r);
    int lc=bl[l],rc=bl[r];
    int out,cd;
    if(lc==rc)
    {
        out=r-L[lc]+1;
        while(out)
        {
            tmp.push_back(code[lc].front());
            code[lc].pop_front();
            --out;
        }
        cd=tmp.back();tmp.pop_back();
        out=r-l;
        while(out)
        {
            code[lc].push_front(tmp.back());
            tmp.pop_back();
            --out;
        }
        code[lc].push_front(cd);
        while(tmp.size())
        {
            code[lc].push_front(tmp.back());
            tmp.pop_back();
        }
        return;
    }
    cd=code[lc].back();
    code[lc].pop_back();
    cnt[lc][cd]--;
    //chu("out:%d\n",cd);
    for(rint i=lc+1;i<rc;++i)
    {
        code[i].push_front(cd);
        cnt[i][cd]++;
        cd=code[i].back();
        code[i].pop_back();
        cnt[i][cd]--;
    }
    code[rc].push_front(cd);
    cnt[rc][cd]++;
    out=r-L[rc]+1;
    while(out)
    {
        tmp.push_back(code[rc].front());
        code[rc].pop_front();
        out--;
    }
    cd=code[rc].front();code[rc].pop_front();
    cnt[rc][cd]--;
    while(tmp.size())
    {
        code[rc].push_front(tmp.back());
        tmp.pop_back();
    }
    out=R[lc]-l;
    while(out)
    {
        tmp.push_back(code[lc].back());
        code[lc].pop_back();
        out--;
    }
    code[lc].push_back(cd);
    cnt[lc][cd]++;
    while(tmp.size())
    {
        code[lc].push_back(tmp.back());
        tmp.pop_back();
    }
}
inline int query(int l,int r,int cor)
{
    int lc=bl[l],rc=bl[r];
    int ans=0;
    if(lc==rc)
    {
        int lp=l-L[lc],rp=r-L[lc];
        for(rint i=lp;i<=rp;++i)ans+=(code[lc][i]==cor);
        return ans;
    }
    int out=R[lc]-l+1;
    while(out)
    {
        tmp.push_back(code[lc].back());
        ans+=(cor==code[lc].back());
        code[lc].pop_back();
        --out;
    }
    while(tmp.size())
    {
        code[lc].push_back(tmp.back());
        tmp.pop_back();
    }
    for(rint i=lc+1;i<rc;++i)ans+=cnt[i][cor];
    out=r-L[rc]+1;
    while(out)
    {
        tmp.push_back(code[rc].front());
        ans+=(cor==code[rc].front());
        code[rc].pop_front();
        --out;
    }
    while(tmp.size())
    {
        code[rc].push_front(tmp.back());
        tmp.pop_back();
    }
    return ans;
}
int main()
{
   // freopen("1.in","r",stdin);
 //   freopen("2.out","w",stdout);
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=re();
    for(rint i=1;i<=n;++i)a[i]=re();
    block=sqrt(n);
    dcc=n/block;
    for(rint i=1;i<=dcc;++i)
    L[i]=R[i-1]+1,R[i]=L[i]+block-1;
    R[dcc]=n;
    for(rint i=1;i<=dcc;++i)
    {
        for(rint j=L[i];j<=R[i];++j)bl[j]=i,++cnt[i][a[j]],code[i].push_back(a[j]);//,chu("bl[%d]:%d\n",j,i);//放颜色
    }
    q=re();
    for(rint i=1;i<=q;++i)
    {
       // chu("new ronud\n");
        int opt=re();

        if(opt==1)
        {
            int l=re(),r=re();
            l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
            if(l>r)swap(l,r);
            change(l,r);
        }
        else
        {
            int l=re(),r=re(),x=re();
           l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
           x=(x+lastans-1)%n+1;
           if(l>r)swap(l,r);
           // chu("he query:%d--%d\n",l,r);
            chu("%d\n",lastans=query(l,r,x));
        }
        // for(rint j=1;j<=dcc;++j)
        // {
        //     for(rint ele:code[j])chu("%d ",ele);
        // }
        // chu("\n");
    }
    return 0;

}
/*
7
7 6 6 3 2 2 1 
6
1 1 1
1 2 6
1 1 3
1 3 5
1 1 6
2 3 7 3
*/
posted on 2022-04-14 10:32  HZOI-曹蓉  阅读(22)  评论(0)    收藏  举报