zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj5341:loj2553:uoj400:p4565:[Ctsc2018]暴力写挂

    题目大意

    有两棵(n)((nleq366666))个节点的树,(T)(T'),有边权
    (dep(i))表示在(T)(i)号点到(1)号点的距离,(dep'(i))表示在(T')(i)号点到(1)号点的距离
    (lca(i,j))表示在(T)(i)号点到(j)号点的简单路径上到(1)号点边数最少的点,(lca'(i,j))表示在(T')(i)号点到(j)号点的简单路径上到(1)号点边数最少的点
    (max(dep(x)+dep(y)-dep(lca(x,y))-dep'(lca'(x,y))))

    题解

    (dis(x,y))表示在(T)(x)号点到(y)号点的距离
    原式变为(max(frac{1}{2}*(dep(x)+dep(y)-dis(x,y))-dep'(lca'(x,y))))
    枚举两点在(T')中的lca,那么剩下的部分只和两点在(T)中的深度、距离有关,与(T)中lca无关,将(dep(x),dep(y))看成点权,(T)变为无根树,可以进行点分治或边分治,求出一对点在(T)中的距离加两点点权的最大值。
    也就是说,要先计算(T')中某点前(k-1)棵子树和该点第(k)棵子树对答案的影响,然后再将第(k)棵子树与前(k-1)棵子树合并
    这个可以在点(边)分树在合并时计算
    点分树合并没有复杂度保证;边分树长得像线段树,合并时也可以类似线段树合并

    代码
    #include<algorithm>
    #include<cmath>
    #include<complex>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 366670
    #define maxn2 (maxn<<1) 
    #define maxn4 (maxn<<2)
    #define LL long long
    #define mi (l+r>>1)
    #define ls(u) (son[u][0])
    #define rs(u) (son[u][1])
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(LL x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    struct edge{int nxt,v;int w;}e0[maxn2],e1[maxn2],e2[maxn4];
    int n,siz[maxn2],vis[maxn4],cnt0,cnt1,cnt2,fir[maxn],fir1[maxn],fir2[maxn2],st[22][maxn4],lg[maxn4],tim,dfn[maxn2],dep[maxn2],wk,mnsz,nd,nowsiz;
    int to[maxn4*5],bac[maxn2],son[maxn4*22][2],rt[maxn2],cntnd;
    LL dep2[maxn2],len[maxn4*22],ans,maxm,inf[2];
    void ade(int u1,int v1,int w1){e0[cnt0].v=v1,e0[cnt0].w=w1,e0[cnt0].nxt=fir[u1],fir[u1]=cnt0++;}
    void ade1(int u1,int v1,int w1){e1[cnt1].v=v1,e1[cnt1].w=w1,e1[cnt1].nxt=fir1[u1],fir1[u1]=cnt1++;}
    void ade2(int u1,int v1,int w1){e2[cnt2].v=v1,e2[cnt2].w=w1,e2[cnt2].nxt=fir2[u1],fir2[u1]=cnt2++;}
    void getsiz(int u,int fa)
    {
        siz[u]=1;
        for(int k=fir2[u];k!=-1;k=e2[k].nxt)
            if(e2[k].v!=fa&&!vis[k]&&!vis[k^1])
            {
                getsiz(e2[k].v,u),siz[u]+=siz[e2[k].v];
                if(max(siz[e2[k].v],nowsiz-siz[e2[k].v])<mnsz)mnsz=max(siz[e2[k].v],nowsiz-siz[e2[k].v]),wk=k;
            }
    }
    int Lca2(int x,int y)
    {
        x=dfn[x],y=dfn[y];
        if(x>y)swap(x,y);
        return dep[st[lg[y-x+1]][x]]<dep[st[lg[y-x+1]][y-(1<<lg[y-x+1])+1]]?st[lg[y-x+1]][x]:st[lg[y-x+1]][y-(1<<lg[y-x+1])+1];
    }
    inline LL dis2(int x,int y){return dep2[x]+dep2[y]-2ll*dep2[Lca2(x,y)];}
    void getwt(int now,int u)
    {
        if(nowsiz==1){to[u]=-now;bac[now]=u;return;}
        mnsz=nd+1;
        getsiz(now,0);int nowk=wk;
        to[u]=nowk;
        vis[nowk]=vis[nowk^1]=1;
        int siz1=siz[e2[nowk].v],siz2=siz[e2[nowk^1].v];
        if(siz1>siz2)siz1=nowsiz-siz2;
        else siz2=nowsiz-siz1;
        nowsiz=siz1,getwt(e2[nowk].v,u<<1),nowsiz=siz2,getwt(e2[nowk^1].v,u<<1|1);
    }
    void get2(int u,int fa)
    {
        int f=0,lst;
        for(int k=fir[u];k!=-1;k=e0[k].nxt)if(e0[k].v!=fa)lst=e0[k].v;
        for(int k=fir[u];k!=-1;k=e0[k].nxt)
            if(e0[k].v!=fa)
            {
                if(!f)ade2(u,e0[k].v,e0[k].w),ade2(e0[k].v,u,e0[k].w),f=u;
                else 
                {
                    if(lst!=e0[k].v)nd++,ade2(f,nd,0),ade2(nd,f,0),ade2(nd,e0[k].v,e0[k].w),ade2(e0[k].v,nd,e0[k].w),f=nd;
                    else ade2(f,e0[k].v,e0[k].w),ade2(e0[k].v,f,e0[k].w);
                }
                get2(e0[k].v,u);
            }
    }
    void getst(int u)
    {
        dfn[u]=++tim;st[0][tim]=u;
        for(int k=fir2[u];k!=-1;k=e2[k].nxt)
            if(!dfn[e2[k].v])dep2[e2[k].v]=dep2[u]+(LL)e2[k].w,dep[e2[k].v]=dep[u]+1,getst(e2[k].v),st[0][++tim]=u;
    }
    int getrt(int node)
    {
        int now=bac[node],u,lst=0,f;
        while(now)
        {
            u=++cntnd;
            if(lst)son[u][f]=lst;
            if(now>>1)len[u]=dis2(node,e2[to[(now>>1)]].v)+dep2[node];
            f=0,lst=u;
            if((((now>>1)<<1)|1)==now)f=1;
            now>>=1;
        }
        return u;
    }
    void merge(int ua,int ub)
    {
         if(ls(ua)&&rs(ub))maxm=max(maxm,(len[ls(ua)]+len[rs(ub)])/2ll);
         if(rs(ua)&&ls(ub))maxm=max(maxm,(len[rs(ua)]+len[ls(ub)])/2ll);
         len[ua]=max(len[ua],len[ub]);
         if(ls(ub))
         {
         	if(ls(ua))merge(ls(ua),ls(ub));
         	else ls(ua)=ls(ub);
         }
         if(rs(ub))
         {
         	if(rs(ua))merge(rs(ua),rs(ub));
         	else rs(ua)=rs(ub);
         }
         return;
    }
    void getans(int u,int fa,LL nowdep)
    {
        rt[u]=getrt(u);
        for(int k=fir1[u];k!=-1;k=e1[k].nxt)
            if(e1[k].v!=fa)getans(e1[k].v,u,nowdep+e1[k].w);
        maxm=dep2[u];
        for(int k=fir1[u];k!=-1;k=e1[k].nxt)
            if(e1[k].v!=fa)merge(rt[u],rt[e1[k].v]); 
        ans=max(ans,maxm-nowdep);
    }
    int main()
    {
        memset(fir,-1,sizeof(fir));
        memset(fir1,-1,sizeof(fir1));
        memset(fir2,-1,sizeof(fir2));
        memset(inf,0x7f,sizeof(inf));
        n=nd=read();
        rep(i,1,n-1){int x=read(),y=read(),z=read();ade(x,y,z),ade(y,x,z);}
        rep(i,1,n-1){int x=read(),y=read(),z=read();ade1(x,y,z),ade1(y,x,z);}
        get2(1,0);
        getst(1); lg[0]=-1;
        rep(i,1,tim)lg[i]=lg[i>>1]+1;
        rep(k,1,lg[tim])for(int i=1;i+(1<<k)-1<=tim;++i)
            st[k][i]=dep[st[k-1][i]]<dep[st[k-1][i+(1<<k-1)]]?st[k-1][i]:st[k-1][i+(1<<k-1)];
        nowsiz=nd;ans=-inf[0];
        getwt(1,1);
        getans(1,0,0);
        write(ans);
        return 0;
    }
    
  • 相关阅读:
    Python一键安装缺失库
    Python画樱花树❀
    Python时间模块time
    Python的画五角星
    力扣225.用队列实现栈
    STL是个啥?
    如何使用递归遍历对象获得value值
    JS操作未跨域iframe里的DOM
    CSS3D效果
    前端轮播小结
  • 原文地址:https://www.cnblogs.com/xzyf/p/10059424.html
Copyright © 2011-2022 走看看