Submission #1150741

#TimeUsernameProblemLanguageResultExecution timeMemory
1150741WarinchaiGrapevine (NOI22_grapevine)C++20
100 / 100
259 ms102428 KiB
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q;
vector<int>adj[400005];
int w[900005];
int have[900005];
map<pair<int,int>,int>mp;
int inf=1e18+5;
struct path{
    int mn,dis;
    path(int x=inf,int d=0){
        mn=x;
        dis=d;
    }
    friend path operator+(path a,path b){
        return path(min(a.mn,b.mn+a.dis),a.dis+b.dis);
    }
}paths[900005],rpaths[900005];
struct point{
    int mn;
    point(int x=inf){
        mn=x;
    }
    friend point operator+(point a,point b){
        return point(min(a.mn,b.mn));
    }
}points[900005];
path compress(path a,path b){
    return a+b;
}
path add_vertex(point x,int i){
    return path(min(x.mn+w[i],have[i]),w[i]);
}
path vertex(int i){
    return path(have[i],w[i]);
}
point rake(point a,point b){
    return a+b;
}
point add_edge(path x){
    return point(x.mn);
}
struct stttree{
    int hv[400005],sz[400005],type[900005],l[900005],r[900005],p[900005],pa[400005],id,rt;
    void dfs(int u,int p){
        //cerr<<"dfs:"<<u<<"\n";
        sz[u]=1;
        pa[u]=p;
        for(auto x:adj[u])if(x!=p){
            dfs(x,u);
            sz[u]+=sz[x];
            if(sz[x]>sz[hv[u]])hv[u]=x;
        }
    }
    void build(int u){
        dfs(u,0);
        id=2*n-1;
        rt=compress(u).first;
    }
    int add(int u,int lch,int rch,int t){
        if(!u)u=++id;
        if(lch)p[lch]=u;
        if(rch)p[rch]=u;
        l[u]=lch,r[u]=rch,type[u]=t;
        return u;
    }
    pair<int,int>merge(vector<pair<int,int>>v,int t){
        if(v.size()==1)return v[0];
        vector<pair<int,int>>l,r;
        int sz=0;
        for(auto x:v)sz+=x.second;
        for(auto x:v){
            if(sz>=x.second)l.push_back(x);
            else r.push_back(x);
            sz-=2*x.second;
        }
        auto ll=merge(l,t);
        auto rr=merge(r,t);
        return {add(0,ll.first,rr.first,t),ll.second+rr.second};
    }
    pair<int,int>compress(int u){
        vector<pair<int,int>>v;
        for(;u;u=hv[u])v.push_back(add_vertex(u));
        return merge(v,1);
    }
    pair<int,int>add_vertex(int u){
        pair<int,int>x=rake(u);
        return {add(u,x.first,0,x.first?2:3),x.second+1};
    }
    pair<int,int>rake(int u){
        vector<pair<int,int>>v;
        for(auto x:adj[u])if(x!=pa[u]&&x!=hv[u])v.push_back(add_edge(x));
        return v.empty()?make_pair(0LL,0LL):merge(v,4);
    }
    pair<int,int>add_edge(int u){
        pair<int,int>x=compress(u);
        return {add(0,x.first,0,5),x.second};
    }
}tr;
point rec(int u){
    path above,below;
    int p=tr.p[u];
    while(tr.type[p]==1){
        if(tr.l[p]==u)below=below+paths[tr.r[p]];
        else above=above+rpaths[tr.l[p]];
        u=p;
        p=tr.p[u];
    }
    if(p){
        u=p;
        p=tr.p[u];
        point temp;
        while(tr.type[p]==4){
            temp=temp+points[(tr.l[p]==u?tr.r[p]:tr.l[p])];
            u=p;
            p=tr.p[u];
        }
        temp=temp+rec(p);
        path x=add_vertex(temp,p);
        above=above+x;
    }
    return point(above.mn)+point(below.mn);
}
int reroot(int u){
    point temp;
    if(tr.type[u]==2)temp=temp+points[tr.l[u]];
    temp=temp+rec(u);
    return add_vertex(temp,u).mn;
}
void upd(int u,int t){
    //cerr<<"u:"<<u<<" ";
    if(t==1){
        paths[u]=compress(paths[tr.l[u]],paths[tr.r[u]]);
        rpaths[u]=compress(rpaths[tr.r[u]],rpaths[tr.l[u]]);
        //cerr<<paths[u].mn<<" "<<paths[u].dis<<"\n";
    }else if(t==2){
        paths[u]=rpaths[u]=add_vertex(points[tr.l[u]],u);
        //cerr<<paths[u].mn<<" "<<paths[u].dis<<"\n";
    }else if(t==3){
        paths[u]=rpaths[u]=vertex(u);
        //cerr<<paths[u].mn<<" "<<paths[u].dis<<"\n";
    }else if(t==4){
        points[u]=rake(points[tr.l[u]],points[tr.r[u]]);
        //cerr<<points[u].mn<<"\n";
    }else{
        points[u]=point(paths[tr.l[u]].mn);
        //cerr<<points[u].mn<<"\n";
    }
}
void dfs(int u){
    //cerr<<"u:"<<u<<" "<<tr.type[u]<<" "<<tr.l[u]<<" "<<tr.r[u]<<"\n";
    if(tr.l[u])dfs(tr.l[u]);
    if(tr.r[u])dfs(tr.r[u]);
    upd(u,tr.type[u]);
}
int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>q;
    for(int i=1;i<=9*n;i++)have[i]=inf;
    for(int i=1;i<n;i++){
        int a,b,ww;cin>>a>>b>>ww;
        adj[a].push_back(n+i);
        adj[n+i].push_back(a);
        adj[n+i].push_back(b);
        adj[b].push_back(n+i);
        w[n+i]=ww;
        mp[{a,b}]=mp[{b,a}]=i+n;
        //cerr<<a<<" "<<i+n<<" "<<b<<"\n";
    }
    tr.build(1);
    dfs(tr.rt);
    //cerr<<"\n\n";
    for(int i=0;i<q;i++){
        int t;cin>>t;
        if(t==1){
            int q;cin>>q;
            int ans=reroot(q);
            cout<<(ans==inf?-1:ans)<<"\n";
        }else if(t==2){
            int u;cin>>u;
            if(have[u]==0)have[u]=inf;
            else have[u]=0;
            for(;u;u=tr.p[u])upd(u,tr.type[u]);
            //cerr<<"\n\n";
        }else{
            int a,b,ww;cin>>a>>b>>ww;
            int u=mp[{a,b}];
            w[u]=ww;
            for(;u;u=tr.p[u])upd(u,tr.type[u]);
            //cerr<<"\n\n";
        }
    }
}
#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...