莫队算法

带修莫队算法

莫队算法是一种比较暴力的离线区间查询算法,充分利用前期查询的结果,基于分块的思想进行优化,得到比较优秀的时间复杂度

带修莫队增加了单点修改操作,思想大致如下:

首先记录下每一次查询操作的区间、次序、上一次的修改次序

为了充分优化时间复杂度,将询问按左端点所属区间排序,若左端点在同一区间,再按右端点所在区间排序,这样同一个块中的询问大概在O(n)的时间便可以处理,总的时间复杂度大概是O(n√n)。

保留上一次查询的结果,每次将上一次的查询区间移动到当前区间上来,再看一下上一次的修改次数与当先查询的修改次数,如果多,就该回去,如果少,就改过来。这个操作可以用栈维护,也可以每次修改后将修改值和序列上的值交换,若再次经过这个点,便被换了回去。

 

板子题:

https://www.luogu.org/problemnew/show/P1903

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 10010 ;
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
    return x*f;
}
int ans,n,m,belong[MAXN],a[MAXN],color[MAXN],out[MAXN];
int bnum,qnum,unum;
struct Query{
    int x,y,pre,id;
} query[MAXN];
struct Update{
    int pos,d;
} update[1010];
bool cmp(Query a,Query b)
{
    if(belong[a.x]!=belong[b.x]) return belong[a.x]<belong[b.x];
    if(belong[a.y]!=belong[b.y]) return belong[a.y]<belong[b.y];
    return a.pre<b.pre;
}
inline void add(int p)
{
    if(++color[p]==1) ans++;
}
inline void del(int p)
{
    if(--color[p]==0) ans--;
}
void work(int now,int i)
{
    if(query[i].x<=update[now].pos&&update[now].pos<=query[i].y)
    {
        if(--color[a[update[now].pos]]==0) ans--;
        if(++color[update[now].d]==1) ans++;
    }
    swap(update[now].d,a[update[now].pos]);
}
void MO()
{
    int l=0,r=0,now=0;
    for(int i=1;i<=qnum;i++)
    {
        while(l<query[i].x) del(a[l++]);
        while(l>query[i].x) add(a[--l]);
        while(r<query[i].y) add(a[++r]);
        while(r>query[i].y) del(a[r--]);
        while(now<query[i].pre) work(++now,i);
        while(now>query[i].pre) work(now--,i);
        out[query[i].id]=ans;
    }
    for(int i=1;i<=qnum;i++)
     printf("%d
",out[i]);
}
int main()
{
    n=read();
    m=read();
    bnum=sqrt(n);
    for(register int i=1;i<=n;i++)
     a[i]=read(),belong[i]=(i-1)%bnum+1;
    int a,b; char f[2];
    for(register int i=1;i<=m;i++)
    {
        scanf("%s",f);
        a=read();b=read();
        if(f[0]=='Q'){
            query[++qnum].x=a;
            query[qnum].y=b;
            query[qnum].pre=unum;
            query[qnum].id=qnum;
        }
        else{
            update[++unum].pos=a;
            update[unum].d=b;
        }
    }
    sort(query+1,query+1+qnum,cmp);
    MO();
    return 0;
}
原文地址:https://www.cnblogs.com/yjkhhh/p/8710436.html