QOJ.ac

QOJ

Type: Editorial

Status: Open

Posted by: robertfan

Posted at: 2026-04-16 11:49:20

Last updated: 2026-04-16 11:49:26

Back to Problem

New Editorial for Problem #13168

B

考虑建出这个图的 $kruskal$ 重构树。

那么把一个区间靠岸可以看成把区间上面的点按照 kruskal 重构树上面的 dfs 序排序后用0的边权加相邻的两个点,那么一条边可以替换的就是在 kruskal 重构树上面的 LCA

然后考虑一个点成为 lca 有什么条件。那么一定是在他的两个子树里能选出一对点 $[x,y]$,使询问区间包含 $[x,y]$。

因此就要对于 $fa_s$ 每个儿子 $s$ 的子树内所有点 $u$,求出编号比 $u$ 大的,在 $s$ 子树外而在 $fa_s$ 子树内最小点。

以上是一个 upper_bound 的形式,考虑进行 dsu-on-tree。具体的,一个 $[x,y]$ 必定包含至少一个点不在重儿子子树内。所以只需对每个轻儿子的子树内的点 $v$,求出其它子树内 $v$ 的前驱后继即可。

`后由于区间无包含关系,所以可以类似于点减边容斥的形式,将包含相邻2个的贡献减去,于是就是二维数点,树状树组维护即可。

#include <bits/stdc++.h>
using namespace std;
vector<tuple<int,int,int> >vec;
int fa[200005];
vector<int>g[200005];
int ff(int x){
    return fa[x]==x?x:fa[x]=ff(fa[x]);
}
set<int>ve[200005];
vector<pair<int,int> >G[200005];
void addd(int L,int R,int tp){
    G[R].push_back({L,tp});
    // cout<<L<<' '<<R<<' '<<tp<<'\n';
}
int W[200005];
void dfs(int u){
    vector<pair<int,int> >pr;
    for(int v:g[u]){
        dfs(v);
    }
    if(g[u].size()){
        if(ve[g[u][0]].size()<ve[g[u][1]].size()){
            swap(g[u][0],g[u][1]);
        }
        swap(ve[g[u][0]],ve[u]);
        for(int v:ve[g[u][1]]){
            auto it=ve[u].lower_bound(v);
            if(it!=ve[u].end()){
                pr.push_back({v,(*it)});
            }
            if(it!=ve[u].begin()){
                pr.push_back({(*prev(it)),v});
            }
        }
        for(int v:ve[g[u][1]]){
            ve[u].insert(v);
        }
    }else{
        ve[u].insert(u);
    }
    sort(pr.begin(),pr.end());
    for(int i=0;i<pr.size();i++){
        addd(pr[i].first,pr[i].second,W[u]);
    }
    for(int i=1;i<pr.size();i++){
        addd(pr[i-1].first,pr[i].second,-W[u]);
    }
}
vector<pair<int,int> >qr[200005];
long long tr[200005];
void add(int pos,int val){
    for(;pos<=100000;pos+=(pos&-pos)){
        tr[pos]+=val;
    }
}
long long ask(int pos){
    long long ans=0;
    for(;pos;pos-=(pos&-pos)){
        ans+=tr[pos];
    }
    return ans;
}
long long ans[200005];
int main(){freopen("flow.in","r",stdin);freopen("flow.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int n,m,q;
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        fa[i]=i;
    }
    long long all=0;
    for(int i=1;i<=m;i++){
        int u,v,c;
        cin>>u>>v>>c;
        u++;
        v++;
        vec.push_back({c,u,v});
    }
    sort(vec.begin(),vec.end());
    int tot=n;
    for(auto [w,u,v]:vec){
        if(ff(u)!=ff(v)){
            all+=w;
            tot++;
            g[tot].push_back(ff(u));
            g[tot].push_back(ff(v));
            fa[ff(v)]=fa[ff(u)]=fa[tot]=tot;
            W[tot]=w;
            // cout<<u<<' '<<v<<'\n';
        }
    }
    dfs(tot);
    for(int i=1;i<=q;i++){
        int l,r;
        cin>>l>>r;
        l++;
        r++;
        qr[r].push_back({l,i});
    }
    for(int i=1;i<=n;i++){
        for(auto [pos,val]:G[i]){
            add(1,val);
            add(pos+1,-val);
            // cout<<pos<<' '<<val<<'\n';
        }
        for(auto [L,id]:qr[i]){
            ans[id]=ask(L);
            // cout<<L<<'-'<<id<<'\n';
        }
    }
    for(int i=1;i<=q;i++){
        cout<<all-ans[i]<<'\n';
    }
    return 0;
}

Comments

No comments yet.