Submission #1151159

#TimeUsernameProblemLanguageResultExecution timeMemory
115115912345678Grapevine (NOI22_grapevine)C++20
100 / 100
1422 ms154168 KiB
#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int nx=1e5+5, kx=17;

struct node
{
    ll mn, lz;
    node(): mn(0), lz(0){}
};

ll n, q, u, v, w, in[nx][kx], out[nx][kx], pa[nx], sz[nx], lvl[nx], used[nx], dif, t, open[nx], cur, segsz[nx], cnt, res;
vector<ll> d[nx];
vector<node> seg[nx];
map<pair<ll, ll>, ll> mp;
vector<tuple<ll, ll, ll>> edg;

int dfssz(int u, int p)
{
    sz[u]=1;
    for (auto v:d[u]) if (v!=p&&!used[v]) sz[u]+=dfssz(v, u);
    return sz[u];
}

int findcentroid(int u, int p, int rtsz)
{
    for (auto v:d[u]) if (v!=p&&!used[v]&&2*sz[v]>rtsz) return findcentroid(v, u, rtsz);
    return u;
}

void dfseulor(int u, int p, int hdlvl)
{
    in[u][hdlvl]=++t;
    for (auto v:d[u]) if (v!=p&&!used[v]) dfseulor(v, u, hdlvl);
    out[u][hdlvl]=t;
}

void decomposition(int u, int p)
{
    u=findcentroid(u, u, dfssz(u, u));
    used[u]=1;
    if (p!=-1) lvl[u]=lvl[p]+1;
    pa[u]=p;
    t=0;
    dfseulor(u, u, lvl[u]);
    segsz[u]=t;
    seg[u].resize(4*segsz[u]+5);
    for (auto v:d[u]) if (!used[v]) decomposition(v, u);
}

void pushlz(int idx, int l, int r, int i)
{
    seg[idx][i].mn+=seg[idx][i].lz;
    if (l!=r) seg[idx][2*i].lz+=seg[idx][i].lz, seg[idx][2*i+1].lz+=seg[idx][i].lz;
    seg[idx][i].lz=0;
}

void updateseg(int idx, int l, int r, int i, int ql, int qr, ll vl)
{
    pushlz(idx, l, r, i);
    if (qr<l||r<ql) return;
    if (ql<=l&&r<=qr) return seg[idx][i].lz=vl, pushlz(idx, l, r, i), void();
    int md=(l+r)/2;
    updateseg(idx, l, md, 2*i, ql, qr ,vl);
    updateseg(idx, md+1, r ,2*i+1, ql, qr ,vl);
    seg[idx][i].mn=min(seg[idx][2*i].mn, seg[idx][2*i+1].mn);
}

ll queryseg(int idx, int l, int r, int i, int ql, int qr)
{
    pushlz(idx, l, r, i);
    if (qr<l||r<ql) return 2e18;
    //if (ql==qr) cout<<"here "<<idx<<' '<<l<<' '<<r<<' '<<ql<<' '<<seg[idx][i].mn<<'\n';
    if (ql<=l&&r<=qr) return seg[idx][i].mn;
    int md=(l+r)/2;
    //ll vll=queryseg(idx, l, md, 2*i ,ql , qr), vlr=queryseg(idx, md+1, r, 2*i+1, ql, qr);
    //if (ql==qr) cout<<"return "<<idx<<' '<<l<<' '<<r<<' '<<ql<<' '<< vll<<' '<<vlr<<'\n';
    return min(queryseg(idx, l, md, 2*i ,ql , qr), queryseg(idx, md+1, r, 2*i+1, ql, qr));
}

void showseg(int idx, int l, int r, int i)
{
    pushlz(idx, l, r, i);
    if (l==r) return cout<<"show "<<idx<<' '<<l<<' '<<seg[idx][i].mn<<'\n', void();
    int md=(l+r)/2;
    showseg(idx, l, md, 2*i);
    showseg(idx, md+1, r, 2*i+1);
}

void updateedge(int u, int v, int w)
{
    if (u>v) swap(u, v);
    dif=w-mp[{u, v}];
    mp[{u, v}]=w;
    if (lvl[u]<lvl[v]) cur=u;
    else cur=v;
    while (cur!=-1)
    {
        if (in[u][lvl[cur]]<=in[v][lvl[cur]]&&out[v][lvl[cur]]<=out[u][lvl[cur]]) updateseg(cur, 1, segsz[cur], 1, in[v][lvl[cur]], out[v][lvl[cur]], dif);
        else updateseg(cur, 1, segsz[cur], 1, in[u][lvl[cur]], out[u][lvl[cur]], dif);
        cur=pa[cur];
    }
}

void updatenode(int u)
{
    if (open[u]) open[u]=0, dif=1e18, cnt--;
    else open[u]=1, dif=-1e18, cnt++;
    cur=u;
    while (cur!=-1)
    {
        updateseg(cur, 1, segsz[cur], 1, in[u][lvl[cur]], in[u][lvl[cur]], dif);
        cur=pa[cur];
    }
}

ll query(int u)
{
    if (cnt==0) return -1;
    cur=u;
    res=1e18;
    while (cur!=-1)
    {
        ll dist=queryseg(cur, 1, segsz[cur], 1, in[u][lvl[cur]], in[u][lvl[cur]]);
        if (dist>=1e18) dist-=(ll)1e18;
        //cout<<"in "<<in[u][lvl[cur]]<<'\n';
        //cout<<"dist "<<cur<<' '<<u<<' '<<dist<<'\n';
        //showseg(cur, 1, segsz[cur], 1);
        res=min(res, dist+queryseg(cur, 1, segsz[cur], 1, 1, segsz[cur]));
        cur=pa[cur];
    }
    return res;
}

int main()
{
    cin.tie(NULL)->sync_with_stdio(false);
    cin>>n>>q;
    cnt=n;
    for (int i=1; i<n; i++) cin>>u>>v>>w, d[u].push_back(v), d[v].push_back(u), mp[{min(u, v), max(u, v)}]=0, edg.push_back({u, v, w});
    decomposition(1, -1);
    for (int i=1; i<=n; i++) open[i]=1, updatenode(i);
    for (auto [u, v, w]:edg) updateedge(u, v, w);
    //showseg(3, 1, segsz[3], 1);
    while (q--)
    {
        cin>>t;
        if (t==1) cin>>u, cout<<query(u)<<'\n';
        if (t==2) cin>>u, updatenode(u);
        if (t==3) cin>>u>>v>>w, updateedge(u, v, w);
    }
}

/*
7 4
1 2 2
2 3 4
5 6 1
5 3 6
3 7 6
2 4 9
2 6
2 4
2 7
1 1
*/
#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...