• 虚树 模板...


    虚树的话,就是把有用的的结点从树中提取出来,从而不会超时的一种东西

    先把点都读入进来

    按照dfs序排序

    在把相邻的点的LCA加入

    再按照dfs序排序

    然后用栈维护一条祖先后代链

    然后在维护过程中退栈的时候加边就行了

    bzoj_3611大工程

    虚树+dp

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    char rea=0;
    inline void read(int &x)
    {
        x=0;
        while(rea<'0'||rea>'9') rea=getchar();
        while(rea>='0'&&rea<='9') x=x*10+rea-'0',rea=getchar();
    }
    const int N=1000006;
    const ll Inf=1e12;
    int first[N],nt[N<<1],ver[N<<1],e;
    inline void addbian(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,m;
    int timer,vis[N],t[N],con,root;
    int isk[N];
    int fa[N],dep[N],st[N][30],maxk,dfn[N],tim,qi[N],ho[N];
    void dfs(int x)
    {
        dfn[x]=++tim; qi[x]=tim;
        int i;
        for(i=first[x];i!=-1;i=nt[i])
        {
            if(ver[i]==fa[x])    continue;
            fa[ver[i]]=x;
            dep[ver[i]]=dep[x]+1;
            dfs(ver[i]);
        }
        ho[x]=tim;
    }
    void ST()
    {
        while((1<<maxk)<=n) ++maxk; --maxk;
        int i,j;
        mem(st,-1);
        for(i=1;i<=n;++i)
            st[i][0]=fa[i];
        for(j=1;(1<<j)<=n;++j)
            for(i=1;i<=n;++i)
                if(st[i][j-1]!=-1)
                    st[i][j]=st[st[i][j-1]][j-1];
    }
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y]) x^=y,y^=x,x^=y;
        int i;
        for(i=maxk;~i;--i)
            if(dep[x]-(1<<i)>=dep[y])
                x=st[x][i];
        if(x==y) return x;
        for(i=maxk;~i;--i)
            if(st[x][i]!=-1&&st[x][i]!=st[y][i])
                x=st[x][i],y=st[y][i];
        return fa[x];
    }
    
    struct T0v0T
    {
        int first[N],nt[N<<1],ver[N<<1],e;
        void clear()
        {
            int i; e=0;
            for(i=1;i<=con;++i) first[t[i]]=-1;
        }
        inline void addbian(int u,int v)
        {
            ver[e]=v;
            nt[e]=first[u];
            first[u]=e++;
        }
    }h;
    
    int zhan[N],he;
    bool cmp(int a,int b)
    {
        return dfn[a]<dfn[b];
    }
    ll mndep[N],mxdep[N],mnan[N],mxan[N],size[N];
    ll sum[N],ansum;
    void dp(int x,int prr)
    {
        size[x]=0; if(isk[x]==timer) size[x]=1;
        mndep[x]=Inf; if(isk[x]==timer) mndep[x]=dep[x];
        mxdep[x]=0; if(isk[x]==timer) mxdep[x]=dep[x];
        mnan[x]=Inf; mxan[x]=0;
        sum[x]=0; if(isk[x]==timer) sum[x]=dep[x];
        int i,te; ll tt=0,mn=Inf,mn2=Inf,mx=0,mx2=0;
        for(i=h.first[x];i!=-1;i=h.nt[i])
            if(h.ver[i]!=prr)
            {
                dp(h.ver[i],x);
                sum[x]+=sum[h.ver[i]];
                size[x]+=size[h.ver[i]];
                if(mn>mndep[h.ver[i]])
                {
                    mn2=mn;
                    mn=mndep[h.ver[i]];
                }
                else
                    if(mn2>mndep[h.ver[i]])
                        mn2=mndep[h.ver[i]];
                if(mx<mxdep[h.ver[i]])
                {
                    mx2=mx;
                    mx=mxdep[h.ver[i]];
                }
                else
                    if(mx2<mxdep[h.ver[i]])
                        mx2=mxdep[h.ver[i]];
            }
        
        if(isk[x]==timer)
        {
            tt+=1LL*(size[x]-1)*dep[x];
            tt+=1LL*(1)*(sum[x]-dep[x]);
            tt-=1LL*dep[x]*2*(1)*(size[x]-1);
        }
        for(i=h.first[x];i!=-1;i=h.nt[i])
            if(h.ver[i]!=prr)
            {
                tt+=1LL*(size[x]-size[h.ver[i]])*sum[h.ver[i]];
                tt+=1LL*size[h.ver[i]]*(sum[x]-sum[h.ver[i]]);
                tt-=1LL*dep[x]*2*(size[h.ver[i]])*(size[x]-size[h.ver[i]]);
            }
        ansum+=tt/2;
        if(isk[x]==timer)
        {
            if(mn>dep[x])
            {
                mn2=mn;
                mn=dep[x];
            }
            else
                if(mn2>dep[x])
                    mn2=dep[x];
            if(mx<dep[x])
            {
                mx2=mx;
                mx=dep[x];
            }
            else
                if(mx2<dep[x])
                    mx2=dep[x];
        }
        mndep[x]=mn; mxdep[x]=mx;
        mnan[x]=mn+mn2-2*dep[x];
        mxan[x]=mx+mx2-dep[x]*2;
    }
    void work()
    {
        rint i,j; int ycon=con,tt;
        sort(t+1,t+1+con,cmp);
        for(i=1;i<ycon;++i)
        {
            tt=LCA(t[i],t[i+1]);
            if(vis[tt]!=timer)
                t[++con]=tt,vis[tt]=timer;
        }
        sort(t+1,t+1+con,cmp);
        he=0; h.clear();
        
        for(i=1;i<=con;++i)
        {
            if(!he) zhan[++he]=t[i];
            else
            {
                while(he>1&&!(qi[t[i]]>=qi[zhan[he]]&&ho[t[i]]<=ho[zhan[he]]))
                    h.addbian(zhan[he-1],zhan[he]),--he;
                zhan[++he]=t[i];
            }
        }
        while(he>1) h.addbian(zhan[he-1],zhan[he]),--he;
        root=zhan[1];
        
        
        ansum=0;
        dp(root,-1);
        
        ll mn=Inf,mx=0;
        for(i=1;i<=con;++i)
        {
            if(mn>mnan[t[i]]) mn=mnan[t[i]];
            if(mx<mxan[t[i]]) mx=mxan[t[i]];
        }
        printf("%lld %lld %lld
    ",ansum,mn,mx);
    }
    
    int main(){
        
      //freopen("in.in","r",stdin);
        //freopen("out.out","w",stdout);
        
        rint i,j; int tin1,tin2,Q,K,tin;
        mem(first,-1);
        
        read(n);
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2);
            addbian(tin1,tin2);
            addbian(tin2,tin1);
        }
        fa[1]=-1; dfs(1);
        ST();
        read(Q);
        for(i=1;i<=Q;++i)
        {
            read(K); ++timer; con=0;
            for(j=1;j<=K;++j)
                ++con,read(t[con]),vis[t[con]]=timer,isk[t[con]]=timer;
            if(K<2)
            {
                printf("0 0 0
    ");
                continue;
            }
            work();
        }
    }
    bzoj_3611

    bzoj_2286消耗战

    虚树+dp

    最小值要用倍增,树链剖分会T

    开long long

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    char rea=0;
    inline void read(int &x)
    {
        x=0;
        while(rea<'0'||rea>'9') rea=getchar();
        while(rea>='0'&&rea<='9') x=x*10+rea-'0',rea=getchar();
    }
    const int N=250006;
    const int Inf=2e9;
    const ll llInf=1e15;
    int first[N],w[N<<1],nt[N<<1],ver[N<<1],e;
    void addbian(int u,int v,int _w)
    {
        ver[e]=v; w[e]=_w;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,m,K;
    int maxk;
    int t[N],con;
    int zhan[N],he;
    int vis[N],timer;
    
    int fa[N],dep[N],v[N];
    int dfn[N],tim,qi[N],ho[N];
    
    int st[N][30],mn[N][30];
    
    void dfs1(int x)
    {
        dfn[x]=qi[x]=++tim;
        int i;
        for(i=first[x];i!=-1;i=nt[i])
            if(ver[i]!=fa[x])
            {
                fa[ver[i]]=x;
                dep[ver[i]]=dep[x]+1;
                v[ver[i]]=w[i];
                dfs1(ver[i]);
            }
        ho[x]=tim;
    }
    void ST()
    {
        while((1<<maxk)<=n) ++maxk; --maxk;
        rint i,j;
        mem(st,-1); mem(mn,0x7f);
        for(i=1;i<=n;++i)
            st[i][0]=fa[i],mn[i][0]=v[i];
        for(j=1;(1<<j)<=n;++j)
            for(i=1;i<=n;++i)
                if(st[i][j-1]!=-1)
                    st[i][j]=st[st[i][j-1]][j-1],
                    mn[i][j]=min(mn[i][j-1],mn[st[i][j-1]][j-1]);
    }
    int LCA(int x,int y)
    {
        int i;
        if(dep[x]<dep[y]) x^=y,y^=x,x^=y;
        for(i=maxk;~i;--i)
            if(dep[x]-(1<<i)>=dep[y])
                x=st[x][i];
        if(x==y) return x;
        for(i=maxk;~i;--i)
            if(st[x][i]!=-1&&st[x][i]!=st[y][i])
                x=st[x][i],y=st[y][i];
        return fa[x];
    }
    int MN(int x,int y)
    {
        int i,an=Inf;
        if(dep[x]<dep[y]) x^=y,y^=x,x^=y;
        for(i=maxk;~i;--i)
            if(dep[x]-(1<<i)>=dep[y])
            {
                if(an>mn[x][i]) an=mn[x][i];
                x=st[x][i];
            }
        if(x==y) return an;
        for(i=maxk;~i;--i)
            if(st[x][i]!=-1&&st[x][i]!=st[y][i])
            {
                if(an>mn[x][i]) an=mn[x][i];
                if(an>mn[y][i]) an=mn[y][i];
                x=st[x][i],y=st[y][i];
            }
        if(an>mn[x][0]) an=mn[x][0];
        if(an>mn[y][0]) an=mn[y][0];
        return an;
    }
    
    struct T0x0T
    {
        int first[N],w[N<<1],nt[N<<1],ver[N<<1],e;
        void clear()
        {
            int i; e=0;
            for(i=1;i<=con;++i)
                first[t[i]]=-1;
        }
        void addbian(int u,int v,int _w)
        {
            ver[e]=v; w[e]=_w;
            nt[e]=first[u];
            first[u]=e++;
        }
    }h;
    
    ll f[N]; int isk[N],sz[N];
    void dp(int x)
    {
        //printf("x=%d
    ",x);
        f[x]=0;
        int i;
        for(i=h.first[x];i!=-1;i=h.nt[i])
        {
            //printf("x=%d ver=%d w=%d
    ",x,h.ver[i],h.w[i]);
            dp(h.ver[i]);
            if(isk[h.ver[i]]==timer)
                f[x]+=h.w[i];
            else
                f[x]+=min((ll)h.w[i],f[h.ver[i]]);
        }
    }
    
    bool cmp(int a,int b)
    {
        return dfn[a]<dfn[b];
    }
    void work()
    {
        sort(t+1,t+1+con,cmp); rint i; int tt,t1;
        tt=con;
        for(i=1;i<tt;++i)
        {
            t1=LCA(t[i],t[i+1]);
            if(vis[t1]!=timer) t[++con]=t1,vis[t1]=timer;
        }
        sort(t+1,t+1+con,cmp);
        he=0; h.clear();
        for(i=1;i<=con;++i)
        {
            if(!he) zhan[++he]=t[i];
            else
            {
                while( he>1 && (!(qi[zhan[he]]<=qi[t[i]]&&ho[zhan[he]]>=ho[t[i]])) )
                    h.addbian(zhan[he-1],zhan[he],MN(zhan[he-1],zhan[he])),--he;
                zhan[++he]=t[i];
            }
        }
        while(he>1)
            h.addbian(zhan[he-1],zhan[he],MN(zhan[he-1],zhan[he])),--he;
        
    /*    printf("
    ");
        for(i=1;i<=con;++i)
            printf("%d ",t[i]);
        printf("
    ");*/
        
        dp(1);
        printf("%lld
    ",f[1]);
    }
    
    int main(){
        
        //freopen("in.in","r",stdin);
        //freopen("out.out","w",stdout);
        
        rint i,j; int tin1,tin2,tin3;
        mem(first,-1);
        
        read(n);
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2); read(tin3);
            addbian(tin1,tin2,tin3);
            addbian(tin2,tin1,tin3);
        }
        fa[1]=-1; dfs1(1);
        ST();
        
        read(m);
        for(i=1;i<=m;++i)
        {
            read(K); con=0; ++timer;
            t[++con]=1; vis[1]=timer;
            for(j=1;j<=K;++j)
                ++con,read(t[con]),vis[t[con]]=timer,isk[t[con]]=timer;
            work();
        }
    }
    bzoj_2286
  • 相关阅读:
    Longest Palindromic Substring问题
    twosum问题
    longest substring问题
    特殊的ARP
    【转】人肉搜索技巧
    ARP攻击
    Linux kali安装及常用命令收集
    【转】ICMP协议
    SpringBoot集成Mybatis-XML方式通用Mapper
    springMVC的controller中insert()多次,记优惠券被多次领取
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7755927.html
Copyright © 2020-2023  润新知