莫队入门

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

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

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

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

//不等,不问,不犹豫,不回头.
#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\n",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('\n'); 
    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\n",x)
#define putl(x) printf("%lld\n",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\n",x)
#define putl(x) printf("%lld\n",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\n",x)
#define putl(x) printf("%lld\n",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

 

posted @ 2020-05-06 14:25  逆天峰  阅读(161)  评论(0)    收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//