zoukankan      html  css  js  c++  java
  • 莫队算法

    带修莫队算法

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

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

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

    为了充分优化时间复杂度,将询问按左端点所属区间排序,若左端点在同一区间,再按右端点所在区间排序,这样同一个块中的询问大概在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;
    }
  • 相关阅读:
    直面焦虑烦恼 谈谈成长
    Makefile入门1
    递归
    极客时间的专栏
    作者介绍
    1.试除法判定质数 2.分解质因数 质数
    17.没有上司的舞会 树形DP
    17.二分图的最大匹配
    16.染色法判定二分图
    15.Kruskal算法求最小生成树
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/8710436.html
Copyright © 2011-2022 走看看