Submission #275956

#TimeUsernameProblemLanguageResultExecution timeMemory
275956aintaMountains and Valleys (CCO20_day1problem3)C++17
25 / 25
5543 ms252348 KiB
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define N_ 510000
#define SZ 524288
typedef pair<int,int> pii;
int n, m, res, C[N_], PPP[N_], Num[N_], Ed[N_], Dep[N_], ord[N_];
vector<int>E[N_], Ch[N_];
struct Edge{
    int e, d;
};
int Dis[N_], par[N_], D[N_], D2[N_], chk[N_], MD2[N_];
int UD[N_], UD2[N_], UMD2[N_];
int MM1[N_][4], MM2[N_][4];
int MPV1[N_][4], MPV2[N_][4];
struct AA{
    int a, b, c;
};
void DFS(int a, int pp, int d){
    Dis[a]=d;
    par[a]=pp;
    for(auto &x : E[a]){
        if(x!=pp)DFS(x,a,d+1);
    }
}
void DFS2(int a, int pp){
    D[a]=D2[a]=MD2[a]=0;
    par[a]=pp;
    C[a]=1;
    for(auto &x : E[a]){
        if(x==pp||chk[x])continue;
        Dep[x]=Dep[a]+1;
        DFS2(x,a);
        C[a]+=C[x];
        D2[a]=max(D2[a],D[a]+D[x]+1);
        D[a]=max(D[a],D[x]+1);
        MD2[a]=max(MD2[a],MD2[x]);
    }
    MD2[a]=max(MD2[a],D2[a]);
}
void UDT(int *M, int *pv, int a, int b, int sz){
    int i, j;
    for(i=0;i<sz;i++){
        if(M[i]<a){
            for(j=sz-1;j>i;j--){
                M[j]=M[j-1];
                pv[j]=pv[j-1];
            }
            M[i]=a,pv[i]=b;
            break;
        }
    }
}
void DFS3(int a, int pp){
    for(auto &x : E[a]){
        if(x==pp)continue;
        Ch[a].push_back(x);
    }
    int Mx[3]={-5,-5,-5},px[3]={-1,-1,-1};
    int Mx2[2]={-1,-1}, px2[2]={-1,-1};
    if(pp){
        UDT(Mx,px,UD[a],pp,3);
        UDT(Mx2,px2,UMD2[a],pp,2);
    }
    UDT(Mx,px,-1,a,3);
    for(auto &x : Ch[a]){
        UDT(Mx, px, D[x],x,3);
        UDT(Mx2,px2,MD2[x],x,2);
    }
    int i;
    for(auto &x : Ch[a]){
        int d1=-1,d2=-1;
        int M1=-5,M2=-5;
        for(i=0;i<3;i++){
            if(px[i]!=x){
                if(M1==-5)M1=Mx[i];
                else if(M2==-5)M2=Mx[i];
            }
        }
        for(i=0;i<2;i++){
            if(px2[i]!=x){
                d2=Mx2[i];
                break;
            }
        }
        UD[x]=M1+1;
        d2=max(d2,UD[x]);
        if(M1!=-5 && M2!=-5)d2=max(d2, M1+M2+2);
        UMD2[x] = d2;
    }
    for(auto &x : Ch[a])DFS3(x,a);
}

pii Calc(int a, int p1, int p2){
    int i, r2=0;
    int z1=-1,z2=-1;
    for(i=0;i<4;i++){
        if(MPV1[a][i]!=p1&&MPV1[a][i]!=p2){
            if(z1==-1)z1=MM1[a][i];
            else if(z2==-1)z2=MM1[a][i];
        }
        if(MPV2[a][i]!=p1&&MPV2[a][i]!=p2){
            r2=max(r2,MM2[a][i]);
        }
    }
    if(z1!=-1 && z2!=-1)r2 = max(r2,z1+z2);
    if(z1<0)z1=0;
    return pii(z1,r2);
}
int cnt;
void HLD(int a, int ppp){
    Num[a]=++cnt;
    ord[cnt]=a;
    PPP[a]=ppp;
    int Mx=-1,pv=-1;
    for(auto &x : Ch[a]){
        if(Mx<C[x]){
            Mx=C[x],pv=x;
        }
    }
    if(pv!=-1){
        HLD(pv,ppp);
    }
    for(auto &x : Ch[a]){
        if(pv!=x)HLD(x,x);
    }
    Ed[a]=cnt;
}
pii DD[N_], DD2[N_], DD3[N_];
int Pre2[N_], DPre[N_];
struct BB{
    int top, bot;
}Pre1[N_];
struct Node{
    int top, bot;
    int g;
    int d2;
}IT[SZ+SZ];
int INF = 1e9;
Node Merge(Node a, Node b){
    Node r;
    r.top=max(a.top,b.top);
    r.bot=max(a.bot,b.bot);
    r.g=max(max(a.g,b.g),a.top+b.bot);
    r.d2=max(a.d2,b.d2);
    return r;
}
Node GetNode(int b, int e){
    b+=SZ,e+=SZ;
    vector<int>A,B;
    while(b<=e){
        if(b&1)A.push_back(b);
        if(!(e&1))B.push_back(e);
        b=(b+1)>>1,e=(e-1)>>1;
    }
    reverse(B.begin(),B.end());
    int ck=0;
    Node res;
    for(auto &t : A){
        if(!ck){
            ck=1;
            res=IT[t];
            continue;
        }
        else res=Merge(res,IT[t]);
    }
    for(auto &t : B){
        if(!ck){
            ck=1;
            res=IT[t];
            continue;
        }
        else res=Merge(res,IT[t]);
    }
    return res;
}
void ITPut(int a, int tt, int bb, int d2){
    a+=SZ;
    IT[a]={tt,bb,-INF,d2};
    while(a!=1){
        a>>=1;
        IT[a]=Merge(IT[a*2],IT[a*2+1]);
    }
}
int LCA(int a, int b){
    while(PPP[a]!=PPP[b]){
        if(Num[PPP[a]]<Num[PPP[b]])b=par[PPP[b]];
        else a=par[PPP[a]];
    }
    if(Dep[a]<Dep[b])return a;
    return b;
}
int MM;
int GoPath(int a, int l, int &cl){
    int t = a, bef = -1;
    int MB = -1e9;
    while(1){
        if(t==l){
            cl=bef;
            break;
        }
        pii z;
        int bb, ee;
        if(a==t){
            z = DD3[a];
        }
        else{
            z = DD2[bef];
        }
        MM=max(MM,z.second);
        int bot1 = z.first-Dep[t]+1,top1=z.first+Dep[t]+1;
        MM=max(MM,top1+MB);
        MB=max(MB,bot1);

        if(PPP[t]==PPP[l]){
            bb = Num[l]+1, ee = Num[t] - 1;
            cl=ord[bb];
            if(bb<=ee){
                Node tp = GetNode(bb,ee);
                MM=max(MM,max(tp.g,tp.d2));
                MM=max(MM, MB+tp.top);
                MB=max(MB,tp.bot);
            }
            break;
        }
        else{
            bb = Num[PPP[t]], ee = Num[t] - 1;
            if(bb<=ee){
                MM=max(MM,Pre2[ee]);
                MM=max(MM,DPre[ee]);
                MM=max(MM,MB+Pre1[ee].top);
                MB=max(MB,Pre1[ee].bot);
            }
        }
        bef = PPP[t];
        t=par[PPP[t]];
    }
    return MB;
}

void Go(int a, int b, int c){
    int l = LCA(a,b);
    MM=-1e9;
    int ca=-1,cb=-1;
    int MB1 = GoPath(a,l,ca);
    int MB2 = GoPath(b,l,cb);
    pii zz = Calc(l,ca,cb);
    MM=max(MM,zz.second);
    int tt = zz.first+Dep[l]+1;
//    printf("%d\n",MM);
 //   printf("%d %d\n",DD3[5].first,DD3[5].second);
 //   printf("%d %d\n",MB1,MB2);
    MM=max(MM,max(MB1,MB2)+tt);
//    printf("%d %d %d %d\n",MB1,MB2,ca,cb);
    MM=max(MM,MB1+MB2+Dep[l]*2);
//    printf("%d %d %d\n",a,b,l);

    int base = 2*(n-1)+c-(Dep[a]+Dep[b]-Dep[l]*2);
//    printf("%d %d %d %d\n",a,b,base,MM);
    res=min(res,base-MM);
}
int main(){
    int i, a, b, c, j;
    scanf("%d%d",&n,&m);
    vector<AA>V;
    for(i=0;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        a++,b++;
        if(c==1){
            E[a].push_back(b);
            E[b].push_back(a);
        }
        else{
            V.push_back({a,b,c});
        }
    }
    DFS(1,0,0);
    int Mx=-1, x=-1, y=-1;
    for(i=1;i<=n;i++)if(Mx < Dis[i])Mx=Dis[i],x=i;
    DFS(x,0,0);
    Mx=-1;
    for(i=1;i<=n;i++)if(Mx < Dis[i])Mx=Dis[i],y=i;
    res = 2*(n-1)-Mx;

    DFS2(1,0);
    DFS3(1,0);
    HLD(1,1);

    for(i=1;i<=n;i++){
        for(j=0;j<4;j++){
            MM1[i][j]=MM2[i][j]=MPV1[i][j]=MPV2[i][j]=-1;
        }
        for(auto &x : E[i]){
            int d = D[x]+1;
            if(x==par[i])d = UD[i]+1;
            UDT(MM1[i],MPV1[i],d,x,4);
            d = MD2[x];
            if(x==par[i])d = UMD2[i];
            UDT(MM2[i],MPV2[i],d,x,4);
        }
    }
    for(i=2;i<n;i++){
        int x = ord[i];
        int y = ord[i+1];
        DD[x]=Calc(x,y,par[x]);
    }
    for(x=1;x<=n;x++){
        if(par[x])DD2[x] = Calc(par[x],x,par[par[x]]);
        DD3[x] = Calc(x,par[x],-1);
    }
    for(i=1;i<=n;i++){
        int x = ord[i];
        int z = PPP[x];
        int tt = DD[x].first + Dep[x] + 1;
        int bb = DD[x].first - Dep[x] + 1;
        if(x==z){
            Pre1[i]={tt,bb};
            Pre2[i] = DD[x].second;
            DPre[i]=-INF;
        }
        else{
            DPre[i]=max(DPre[i-1],bb+Pre1[i-1].top);
            Pre1[i]={max(tt,Pre1[i-1].top), max(bb,Pre1[i-1].bot)};
            Pre2[i] = max(Pre2[i-1],DD[x].second);
        }
        ITPut(i,tt,bb,DD[x].second);
    }
    for(auto &t : V){
        Go(t.a,t.b,t.c);
    }
    printf("%d\n",res);
}

Compilation message (stderr)

Main.cpp: In function 'void DFS3(int, int)':
Main.cpp:73:13: warning: unused variable 'd1' [-Wunused-variable]
   73 |         int d1=-1,d2=-1;
      |             ^~
Main.cpp: In function 'int main()':
Main.cpp:279:22: warning: variable 'y' set but not used [-Wunused-but-set-variable]
  279 |     int Mx=-1, x=-1, y=-1;
      |                      ^
Main.cpp:265:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  265 |     scanf("%d%d",&n,&m);
      |     ~~~~~^~~~~~~~~~~~~~
Main.cpp:268:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  268 |         scanf("%d%d%d",&a,&b,&c);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...