zoukankan      html  css  js  c++  java
  • 莫队入门

    原来莫队与分块没关系啊.....

    安利好的博客:莫队入门详解

    嗯,莫队就是采用了分块的思想,然后用指针暴力跳....

    对于普通的莫队,比较玄学的就是奇偶性排序比较玄学...

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define db double
    #define RE register
    #define ll long long
    #define P 1000000007
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define pb(x) push_back(x)
    #define ull unsigned long long
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=30010,M=1e6+10;
    int a[N],n,Q,now,cnt[M],belong[N],block,num,c[M];
    struct wy{int l,r,id;}q[M];
    
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,ff=1;
        char ch=getc();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getc();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getc();}
        return x*ff;
    }
    
    inline int put(int x)
    {
        if(x<0) putchar('-'),x=-x;
        if(x/10) put(x/10);
        putchar(x%10+'0');
    }
    
    inline void build()
    {
        block=sqrt(n);num=n/block;
        if(n%block) num++;
        rep(i,1,n) belong[i]=(i-1)/block+1;
    }
    
    inline bool cmp(wy a,wy b) 
    {
        return belong[a.l]!=belong[b.l]?belong[a.l]<belong[b.l]:(belong[a.l]&1?a.r<b.r:a.r>b.r);
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);
        rep(i,1,n) get(a[i]);
        build();get(Q);
        rep(i,1,Q)
        {
            q[i].id=i;
            get(q[i].l);get(q[i].r);
        }
        sort(q+1,q+Q+1,cmp);
        int l=1,r=0,now=0;
        rep(i,1,Q)
        {
            int ql=q[i].l,qr=q[i].r;
            while(l<ql) now-=!--cnt[a[l++]];
            while(l>ql) now+=!cnt[a[--l]]++;
            while(r<qr) now+=!cnt[a[++r]]++;
            while(r>qr) now-=!--cnt[a[r--]];
            c[q[i].id]=now;
        }
        rep(i,1,Q) put(c[i]),putchar('
    '); 
        return (0^_^0);
    }
    //以吾之血,祭吾最后的亡魂
    View Code

    带修莫队,记得将块长定义为n^(2/3)次方,这样他的复杂度就成了n(5/3).暴力跳time就行了.

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define db double
    #define RE register
    #define ll long long
    #define P 1000000007
    #define INF 1000000000
    #define get(x) x=read()
    #define PII pair<int,int>
    #define PLI pair<ll,int>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define pb(x) push_back(x)
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=140000,M=1e6+10;
    int a[N],n,m,c[N],cnt[M],belong[N],block;
    struct wy{int l,r,time,id;}q[N];
    struct jl{int pos,color;}b[N];
    char ch[10];
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    inline void build()
    {
        block=pow(n,2.0/3.0);
        rep(i,1,n) belong[i]=(i-1)/block+1;
    }
    
    inline bool cmp(wy a,wy b)
    {
        return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.r]^belong[b.r])?belong[a.r]<belong[b.r]:a.time<b.time);
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);get(m);
        rep(i,1,n) get(a[i]);
        build();
        int cntq=0,cntc=0;
        rep(i,1,m)
        {
            scanf("%s",ch);
            if(ch[0]=='Q') 
            {
                get(q[++cntq].l);
                get(q[cntq].r);
                q[cntq].time=cntc;
                q[cntq].id=cntq; 
            }    
            else 
            {
                get(b[++cntc].pos);
                get(b[cntc].color);
            }
        }
        sort(q+1,q+cntq+1,cmp);
        int l=1,r=0,time=0,now=0;
        rep(i,1,cntq)
        {
            int ql=q[i].l,qr=q[i].r,qt=q[i].time;
            while(l<ql)now-=!--cnt[a[l++]];
             while(l>ql)now+=!cnt[a[--l]]++;
             while(r<qr)now+=!cnt[a[++r]]++;
             while(r>qr)now-=!--cnt[a[r--]];
             while(time<qt)
             {
                 time++;
                 if(b[time].pos>=ql&&b[time].pos<=qr)
                     now-=!--cnt[a[b[time].pos]]-!cnt[b[time].color]++;
                 swap(a[b[time].pos],b[time].color);
             }
             while(time>qt)
             {
                 if(b[time].pos>=ql&&b[time].pos<=qr)
                     now-=!--cnt[a[b[time].pos]]-!cnt[b[time].color]++;
                 swap(a[b[time].pos],b[time].color);
                 --time;
             }
            c[q[i].id]=now;
        }
        rep(i,1,cntq) put(c[i]);
        return (0^_^0);
    }
    //以吾之血,祭吾最后的亡魂
    View Code

    树上莫队,考虑欧拉序的话,遇见第二次直接删掉,第一次加入的原则,特判下lca就行了.

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define db double
    #define RE register
    #define ll long long
    #define P 1000000007
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define pb(x) push_back(x)
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=40010,M=1e5+10;
    int link[N],tot,n,m,b[N],d[N],ct,ou[N<<1],num,first[N],last[N],f[N][25],deep[N];
    int cnt[N],vis[N],c[M],belong[N],block,now;
    struct edge{int y,next;}a[N<<1];
    struct wy{int l,r,id,lc;}q[M];
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    inline int find(int x){return lower_bound(b+1,b+ct+1,x)-b;}
    
    inline void add(int x,int y)
    {
        a[++tot].y=y;a[tot].next=link[x];link[x]=tot;
        a[++tot].y=x;a[tot].next=link[y];link[y]=tot;
    }
    
    inline void dfs(int x,int fa)
    {
        ou[++num]=x;first[x]=num;
        go(x)
        {
            if(y==fa) continue;
            deep[y]=deep[x]+1;
            f[y][0]=x;
            rep(j,1,20) f[y][j]=f[f[y][j-1]][j-1];
            dfs(y,x);
        }
        ou[++num]=x;last[x]=num;
    }
    
    inline int lca(int a,int b)
    {
        if(deep[a]>deep[b]) swap(a,b);
        fep(i,20,0) if(deep[f[b][i]]>=deep[a]) b=f[b][i];
        if(a==b) return a;
        fep(i,20,0) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
        return f[a][0];
    }
    
    inline bool cmp(wy a,wy b)
    {
        return (belong[a.l]^belong[b.l]?belong[a.l]<belong[b.l]:(belong[a.l]&1?a.r<b.r:a.r>b.r));
    }
    
    inline void work(int x)
    {
        if(vis[x]){cnt[d[x]]--;if(!cnt[d[x]]) now--;}
        else{if(!cnt[d[x]]) now++;cnt[d[x]]++;}
        vis[x]^=1;
    }
    
    inline void build()
    {
        block=sqrt(n<<1);
        rep(i,1,n<<1) belong[i]=(i-1)/block+1;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);get(m);
        build();
        rep(i,1,n) get(d[i]),b[i]=d[i];
        sort(b+1,b+n+1);
        ct=unique(b+1,b+n+1)-b-1;
        rep(i,1,n-1)
        {
            int get(x),get(y);
            add(x,y);
        }
        deep[1]=1;dfs(1,0);
        rep(i,1,m)
        {
            int get(l),get(r),lc=lca(l,r);
            if(first[l]>first[r]) swap(l,r);
            if(lc==l)
            {
                q[i].l=first[l];
                q[i].r=first[r];
            }
            else 
            {
                q[i].l=last[l];
                q[i].r=first[r];
                q[i].lc=lc;
            }
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp);
        int l=1,r=0;
        rep(i,1,m)
        {
            int ql=q[i].l,qr=q[i].r,lc=q[i].lc;
            while(l<ql)    work(ou[l++]);
            while(l>ql) work(ou[--l]);
            while(r<qr) work(ou[++r]);
            while(r>qr) work(ou[r--]);
            if(lc) work(lc);
            c[q[i].id]=now;
            if(lc) work(lc);
    
        }
        rep(i,1,m) put(c[i]); 
        return (0^_^0);
    }
    //以吾之血,祭吾最后的亡魂
    View Code

    回滚莫队,算是最妙的一种莫队,常数最小,考虑属于同一块的左端点,其右端点单调递增,每此暴力跳r指针,然后每个询问将l指针清空即可.所以只需要考虑增加的问题即可.

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define db double
    #define RE register
    #define ll long long
    #define P 1000000007
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define pb(x) push_back(x)
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=1e5+10;
    int n,Q,a[N],num,cnt1[N],cnt2[N];
    int block,bnum,belong[N],bl[N],br[N];
    ll c[N],b[N];
    struct wy{int l,r,id;}q[N];
    
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,ff=1;
        char ch=getc();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getc();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getc();}
        return x*ff;
    }
    
    inline int find(int x) {return lower_bound(b+1,b+num+1,x)-b;}
    
    inline void build()
    {
        block=sqrt(n);bnum=n/block;
        if(n%block) bnum++;
        rep(i,1,n) belong[i]=(i-1)/block+1;
        rep(i,1,bnum) bl[i]=(i-1)*block+1,br[i]=i*block;
        br[bnum]=n;
    }
    
    inline bool cmp(wy a,wy b)
    {
        return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:a.r<b.r;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);get(Q);
        rep(i,1,n) get(a[i]),b[i]=a[i];
        sort(b+1,b+n+1);
        num=unique(b+1,b+n+1)-b-1;
        rep(i,1,n) a[i]=find(a[i]);
        build();
        rep(i,1,Q)
        {
            get(q[i].l);get(q[i].r);
            q[i].id=i;
        }
        sort(q+1,q+Q+1,cmp);
        int i=1;
        rep(j,1,bnum)//枚举每一块. 
        {
            int l=br[j]+1,r=br[j];
            ll now=0;
            memset(cnt1,0,sizeof(cnt1));
            for(;i<=Q&&belong[q[i].l]==j;++i)//枚举这个块里的所有左端点. 
            {
                ll temp;
                int ql=q[i].l,qr=q[i].r;
                if(belong[qr]==belong[ql])
                {
                    temp=0;
                    rep(k,ql,qr) cnt2[a[k]]=0;
                    rep(k,ql,qr) {++cnt2[a[k]];temp=max(temp,b[a[k]]*cnt2[a[k]]);}
                    c[q[i].id]=temp;continue;
                }
                while(r<qr) {++r;++cnt1[a[r]];now=max(now,b[a[r]]*cnt1[a[r]]);}
                temp=now;
                while(l>ql) {--l;++cnt1[a[l]];now=max(now,b[a[l]]*cnt1[a[l]]);}
                c[q[i].id]=now;
                while(l<br[j]+1) {--cnt1[a[l]];++l;}
                now=temp;
            }
        }
        rep(i,1,Q) putl(c[i]);
        return (0^_^0);
    }
    //以吾之血,祭吾最后的亡魂
    View Code
  • 相关阅读:
    groovy集合
    groovy函数、字符串、循环
    groovy运行程序和类型推断
    常见IT英语短语一
    常见IT英语单词
    认识Groovy
    maven入门
    springboot之内嵌tomcat修改端口号
    springboot手动配置数据源:
    img与父元素的间隙解决
  • 原文地址:https://www.cnblogs.com/gcfer/p/12836162.html
Copyright © 2011-2022 走看看