zoukankan      html  css  js  c++  java
  • 莫队

    普通莫队

    块大小取为(sqrt n)

    询问排序时可选择按奇偶性排序

    (code:)

    bool cmp(query a,query b)
    {   
        return (a.r/block)==(b.r/block)?a.l<b.l:a.r<b.r;
    }
    
    bool cmp(query a,query b)
    {   
        return a.pos==b.pos?(a.pos&1?a.r<b.r:a.r>b.r):a.pos<b.pos;
    }
    
    while(l<ql) del(l++);
    while(r>qr) del(r--);
    while(l>ql) add(--l);
    while(r<qr) add(++r);
    

    带修莫队

    将莫队再加上一维,加上时间轴,若当前查询与时间不匹配,则进行时光穿越或时光倒流

    块大小取为(n^frac{2}{3})时最优

    (code:)

    while(l<ql) del(l++);
    while(r>qr) del(r--);
    while(l>ql) add(--l);
    while(r<qr) add(++r);
    
    while(ti<qt)
    {
        ti++;
        int pos=c[ti].pos;
        if(l<=pos&&pos<=r)
        {
            cnt[a[pos]]--;
            if(!cnt[a[pos]]) tot--;
        }
        swap(a[pos],c[ti].col);
        if(l<=pos&&pos<=r)
        {
            cnt[a[pos]]++;
            if(cnt[a[pos]]==1) tot++;
        }
    }
    while(ti>qt)
    {
        int pos=c[ti].pos;
        if(l<=pos&&pos<=r)
        {
            cnt[a[pos]]--;
            if(!cnt[a[pos]]) tot--;
        }
        swap(a[pos],c[ti].col);
        if(l<=pos&&pos<=r)
        {
            cnt[a[pos]]++;
            if(cnt[a[pos]]==1) tot++;
        }
        ti--;
    }
    

    树上莫队

    先预处理出欧拉序,就是原(dfs)序在回溯时又加入序列,每个编号在序列中出现两次

    树的欧拉序上两个相同编号之间的所有编号都出现两次,且都位于其子树上

    设欧拉序中一个节点(x)第一次出现的位置为(st),第二次出现的位置为(ed)

    询问(x)(y),设(st[x] leqslant st[y])

    (lca(x,y)=x),则使用区间([ st[x],st[y] ])

    反之,使用区间([ ed[x],st[y] ]),还需再加上(lca(x,y))

    (code:)

    void dfs_son(int x,int fath)
    {
        st[x]=++num;
        rev[num]=x;
        fa[x]=fath;
        siz[x]=1;
        de[x]=de[fath]+1;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fath) continue;
            dfs_son(y,x);
            siz[x]+=siz[y];
            if(siz[y]>siz[son[x]]) son[x]=y;
        }
        ed[x]=++num;
        rev[num]=x;
    }
    void dfs_chain(int x,int tp)
    {
        top[x]=tp;
        if(son[x]) dfs_chain(son[x],tp);
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(top[y]) continue;
            dfs_chain(y,y);
        }
    }
    int lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(de[top[x]]<de[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(de[x]>de[y]) swap(x,y);
        return x;
    }
    struct query
    {
        int l,r,id,pos,lca;
    }q[maxn];
    bool cmp(query a,query b)
    {   
        return a.pos==b.pos?(a.pos&1?a.r<b.r:a.r>b.r):a.pos<b.pos;
    }
    void add(int x)
    {
        tot+=(++cnt[a[x]]==1);
    }
    void del(int x)
    {
        tot-=(--cnt[a[x]]==0);
    }
    void update(int x)
    {
        if(!vis[x]) add(x);
        else del(x);
        vis[x]^=1;
    }
    
    ......
    
    dfs_son(1,0);
    dfs_chain(1,1);
    for(int i=1;i<=m;++i)
    {
        int x,y,anc;
        read(x),read(y);
        if(st[x]>st[y]) swap(x,y);
        anc=lca(x,y);
        if(anc==x) q[i]=(query){st[x],st[y],i,st[x]/block,0};
        else q[i]=(query){ed[x],st[y],i,ed[x]/block,anc};
    }
    sort(q+1,q+m+1,cmp);
    for(int i=1;i<=m;++i) 
    {
        int ql=q[i].l,qr=q[i].r,id=q[i].id,anc=q[i].lca;
        while(l<ql) update(rev[l++]);
        while(r>qr) update(rev[r--]);
        while(l>ql) update(rev[--l]);
        while(r<qr) update(rev[++r]);
        if(anc) update(anc);
        ans[id]=tot;
        if(anc) update(anc);
    }
    
  • 相关阅读:
    Python 学习笔记(十三)Python函数(二)
    Python 学习笔记(十三)Python函数(一)
    Python 学习笔记(十二)Python文件和迭代(二)
    tb数据过多用省略号显示
    js,el表达式,<c:if>
    html元素标签时间格式化
    oracle链接报错shared memory realm does not exist
    mysql查找字段在哪个表中
    删除数据库重复数据
    excel使用poi操作。
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229611.html
Copyright © 2011-2022 走看看