题目大意:给你一棵树,每个点有点权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. CF1027F Session in BSU (并查集+树上构造)

    题目大意:你可以在第$ai$天或者第$bi$天进行第$i$场考试,每天最多进行一场考试,求把所有考试都考完的最早结束时间 由于天数可能很大,需要离散 把问题抽象成一棵树,每个点最多被"分配& ...

  2. 八、frps服务端与nginx可共用80端口

    我的服务器,已经用nginx 做网站了,80端口只有一个,我还想我的frps一起使用,可以吗?这个是可以实现的,利用nginx的反向代理实现. 以下是在frps服务器上安装的nginx配置文件中设置的 ...

  3. jquery 将函数作为参数传递

    等待执行函数 这是自己封装的layui的询问框 //------[询问框](parameter:执行函数的参数,f_name:执行函数,msg:提示,time:自动消失时间,btn_arr:按钮组,o ...

  4. Linux系统_Ubuntu中Hadoop常用命令

    ctrl+alt+t打开终端窗口sudo useradd -m hadoop -s/bin/bash创建新用户ctrl+alt回到自己的笔记本 创建hadoop用户sudo useradd -m ha ...

  5. 【基于mini2440开发板的交叉编译环境及内核树配置.

    在学习linux驱动开发过程中,交叉编译环境的配置及内核树的生成无疑是对linux不是十分了解的新人面前的一堵墙.高高大大的墙...笔者在初探这一方向时,就在这2个问题上苦恼了很久.查阅无数资料,大多 ...

  6. JavaScript div 上下运动实例

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. Redis介绍、安装部署、操作

    学习连接:http://www.runoob.com/redis/redis-tutorial.html 一.Redis介绍 Redis是NoSql的一种. NoSql,全名:Not Only Sql ...

  8. [CSS3] CSS Background Images

    Body with background image and gradient html { background: linear-gradient(#000, white) no-repeat; h ...

  9. 零基础学HTML 5实战开发(第一季)

    開始学习html5了.趋势不得不学习啊,之前老毛说过落后就要挨打,如今是不学习就要被市场淘汰,被社会淘汰.喜欢挑战,喜欢冒险.来吧.csdn给我们提供了那么好的平台.用起来..零基础学HTML 5的实 ...

  10. 第二次phython作业

    第一题:编写程序,生成一个包含50个随机整数的列表,然后删除其中所有奇数.(注意保证删除操作的效率) import random x=[random.randint(0,100)for i in ra ...