题目大意:给你一棵树,每个点有点权a_{i},求$\sum _{i=1}^{n} \sum _{j=i}^{n} f(i,j)$,$f(i,j)$表示i,j,路径上的点的最大权值-最小权值

正解的思路好神啊

正解:

首先,原式可以拆成$\sum _{i=1}^{n} \sum _{j=i}^{n} max(i,j) \; - \; \sum _{i=1}^{n} \sum _{j=i}^{n} min(i,j)$

max的求法和min类似,这里只讨论min的求法

把点按照从大到小排序,依次加入树里

感性理解成以当前点的点权作为最小值,那么这个点会向它周围已经被加入树里的联通块"扩散"去更新答案

答案就是这个点周围(剩余联通块的点数-当前联通块的点数)*点权,然后 剩余点数-当前联通块点数

也可以省去减法步骤,把最终答案除以二

并查集维护联通块即可,算上排序,总时间约为$O(nlogn)$

 #include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1001000
#define ll long long
using namespace std; int gint()
{
int ret=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*f;
}
int n,cte,tim;
int w[N],head[N],use[N];
int fa[N],sz[N];
void init(){for(int i=;i<=n;i++)fa[i]=i,sz[i]=;}
int find_fa(int x){
int y=x,pre;while(fa[y]!=y)y=fa[y];
while(fa[x]!=y){
pre=fa[x],fa[x]=y,x=pre;
}return y;
}
struct node{int id,val;}a[N];
struct Edge{int to,nxt;}edge[N*];
void ae(int u,int v){
cte++;edge[cte].nxt=head[u];
edge[cte].to=v,head[u]=cte;
}
int cmp(node s1,node s2){return s1.val<s2.val;} ll solve1()
{
sort(a+,a+n+,cmp);
int x,y,fx,fy;
init(); ll ans=;
for(int i=;i<=n;i++)
{
ll sum=;x=a[i].id;
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
if(use[v]){
fy=find_fa(v);
sum+=sz[fy];
}
}sum++;
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
if(use[v]){
fy=find_fa(v);
ans+=1ll*(sum-sz[fy])*sz[fy]*a[i].val;
sum-=sz[fy];
fa[fy]=x,sz[x]+=sz[fy];
}
}
use[x]=;
}return ans;
}
ll solve2()
{
memset(use,,sizeof(use));
int x,y,fx,fy;
init(); ll ans=;
for(int i=n;i>=;i--)
{
ll sum=;x=a[i].id;
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
if(use[v]){
fy=find_fa(v);
sum+=sz[fy];
}
}sum++;
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
if(use[v]){
fy=find_fa(v);
ans+=1ll*(sum-sz[fy])*sz[fy]*a[i].val;
sum-=sz[fy];
fa[fy]=x,sz[x]+=sz[fy];
}
}
use[x]=;
}return ans;
} int main()
{
scanf("%d",&n);
int x,y;
for(int i=;i<=n;i++)
w[i]=a[i].val=gint(),a[i].id=i;
for(int i=;i<n;i++)
x=gint(),y=gint(),ae(x,y),ae(y,x);
ll ans1=solve1();
ll ans2=solve2();
printf("%I64d\n",ans1-ans2);
return ;
}

CF915F Imbalance Value of a Tree (并查集)的更多相关文章

  1. 【CodeForces】915 F. Imbalance Value of a Tree 并查集

    [题目]F. Imbalance Value of a Tree [题意]给定n个点的带点权树,求所有路径极差的和.n,ai<=10^6 [算法]并查集 [题解]先计算最大值的和,按点权从小到大 ...

  2. [CF915F]Imbalance Value of a Tree

    [CF915F]Imbalance Value of a Tree 题目大意: 一棵\(n(n\le10^6)\)个结点的树,每个结点有一个权值\(w_i\).定义\(I(i,j)\)为\(i\)到\ ...

  3. Hdu.1325.Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  4. Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26002   Accepted: 8879 De ...

  5. CF109 C. Lucky Tree 并查集

    Petya loves lucky numbers. We all know that lucky numbers are the positive integers whose decimal re ...

  6. HDU 5606 tree 并查集

    tree 把每条边权是1的边断开,发现每个点离他最近的点个数就是他所在的连通块大小. 开一个并查集,每次读到边权是0的边就合并.最后Ans​i​​=size[findset(i)],size表示每个并 ...

  7. [Swust OJ 856]--Huge Tree(并查集)

    题目链接:http://acm.swust.edu.cn/problem/856/ Time limit(ms): 1000 Memory limit(kb): 10000 Description T ...

  8. Codeforces Round #363 (Div. 2)D. Fix a Tree(并查集)

    D. Fix a Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  9. Is It A Tree?(并查集)(dfs也可以解决)

    Is It A Tree? Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submi ...

随机推荐

  1. CDR X6打了3折,再送魔镜插件,是真的么?

    明人不说暗话,我.要.来.个.小.资.讯. CDR X6打了3折,再送魔镜插件,是真的么?   先来说说CorelDRAW,CorelDRAW众所周知,软件的确不便宜啊,对于个人来说,相当于一个高配苹 ...

  2. 搭建自己的koa+mysql后台模板

    1.在vscode里面打开一个文件夹 2.cnpm init 3.导入必要的依赖项 "dependencies": { "koa": "^2.7.0& ...

  3. Lumen5.5,使用laravel excel 下载 、导入excel文件

    1.安装 首先是安装laravel excel,使用composer安装 composer require maatwebsite/excel ~2.1.0 2.配置 在bootstrap/app.p ...

  4. ubuntu qq2012

    wine qq 2012 for linux Ubuntu 64位兼容(12月21日末日版) 版主: byebye, liyijun, smile, wolfstar 发表回复   340 篇帖子 • ...

  5. Vue - vue.js 常用指令

    Vue - vue.js 常用指令 目录: 一. vuejs模板语法之常用指令 1. 常用指令: v-html 2. 常用指令: v-text 3. 常用指令: v-for 4. 常用指令: v-if ...

  6. 洛谷——P2483 [SDOI2010]魔法猪学院

    https://www.luogu.org/problem/show?pid=2483 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的 ...

  7. Windows下面使用curl

    Windows下面使用curl 学习了:https://www.cnblogs.com/xing901022/p/4652624.html 下载地址:https://curl.haxx.se/down ...

  8. L2CAP数据发送和接收

    ACL 链路在 Bluetooth 中非常重要,一些重要的应用如 A2DP, 基于 RFCOMM 的应用.BNEP等都要建立 ACL 链路,发送/接收ACL 包.跟大家一起来分析 ACL 包发送/接收 ...

  9. 继承QWidget的派生类控件不能设置QSS问题解决(使用style()->drawPrimitive(QStyle::PE_Widget,也就是画一个最简单最原始的QWidget,不要牵扯其它这么多东西)

    自定义控件时基类用了QWidget,发现qss设置不起作用,需要重载其paintEvent函数即可: 如下代码: void CCustomWidget::paintEvent(QPaintEvent* ...

  10. 如何获取Assets的路径

    有两种方法可以获取assets的绝对路径: 第一种方法: String path = file:///android_asset/文件名; 第二种方法: InputStream abpath = ge ...