link

题解

考虑对于一个有根树,每条$fa_v=u$的边的贡献是$w_u$,也就是$(w_u+w_v)-w_v$,由于除了根每个$v$只有一个$f_v$,则总贡献就是$\sum(w_u+w_v)-\sum w_v+w_r$。

建一个超级根,点权为0,原来每个有根树的根设为这个点的儿子。

那么总贡献就是边权和-点权和。

点权和固定了,边权和可以直接最大生成树算。

int a[1<<18|5];
int dis[1<<18|5],cnt[1<<18|5];
priority_queue<int> pq;
const int m=1<<18;
int fa[1<<18|5];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
ll ans;
void link(int u,int v,int w){
    if(cnt[u] && cnt[v]){
        u=find(u);v=find(v);    
        if(u!=v){
            ans+=(ll)w*(cnt[u]+cnt[v]-1);fa[u]=v;cnt[v]=1;
        }
    }
}
signed main(){
#ifdef QAQAutoMaton 
    freopen("G.in","r",stdin);
    freopen("G.out","w",stdout);
#endif
    int n;
    read(n);
    int x;
    for(int i=1;i<=n;++i){
        read(x);
        ++cnt[x];
        ans-=x;
    }
    cnt[m]=1;
    fa[m]=m;
    for(int i=0;i<m;++i){
        fa[i]=i;
    }
    for(int i=m-1;~i;--i){
        for(int j=i;;j=(j-1)&i){
            link(j,i^j,i);    
            if(!j)break;
        }
        link(i,m,i);
    }
    write(ans,'\n');
    return 0;
}

标签: none

添加新评论