边分治学习笔记(bzoj2870)
如果点分治的话,那个取最小点权操作很难合并,不过树可以点分治,那自然也可以边分治。我们每次找到一条边,使得删掉这条边后的两个连通块中最大的那个的大小尽可能小,然后处理经过这条边的路径信息……
桥豆麻袋,这个复杂度好像不太对啊。
在菊花图上,好像可以轻易变成O(n)O(n)O(n)的啊!!!
于是我们就要把树做一下转化,如果一个点有太多个儿子,我们就建立若干个虚拟点来管理它的儿子们,这样这棵树就变成了二叉树,可以保证O(nlogn)O(nlogn)O(nlogn)
我们发现,只要把虚拟点的点权设为原来那个父亲的点权,就不会影响找点权最小值的操作。但是找链条的长度的话,如果两个点的LCA是一个虚拟点的话,它们真实的父亲的贡献就不会被计算。所以我们令真实边的边权为1,虚拟边边权为0,那么一条链的长度就是这条链边权和+1。
这样就好办多了,每次我们找到一条边,使得删掉这条边后的两个连通块中最大的那个的大小尽可能小,然后把边两端的路径存下来,按照点权最小值排序,然后对于A端的一条路径,我们维护B端点权大于等于该路径的路径中,长度最长的一条,对B端也这么做一边就可以得到答案。复杂度O(nlog2n)O(nlog2n)O(nlog^2n)
至于空间,我们知道线段树要开四倍空间,所以对于菊花图,这个重建树就也是四倍空间。
#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {int q=0;char ch=' ';while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();return q;
}
typedef long long LL;
const int N=200005,inf=0x3f3f3f3f;
int n,kn,tot,rt,mxx;LL ans;
int v[N],sz[N],h[N],ne[N<<1],to[N<<1],d[N],vis[N],js[2];
struct node{int v,len;}t[2][N];
bool cmp(node x,node y) {return x.v>y.v;}
vector<int> a[N];
void add(int x,int y,int z) {to[++tot]=y,ne[tot]=h[x],h[x]=tot,d[tot]=z;}
void dfs1(int x,int las) {for(RI i=h[x];i;i=ne[i])if(to[i]!=las) a[x].push_back(to[i]),dfs1(to[i],x);
}
void rebuild() {//重新建树tot=1;for(RI i=1;i<=n;++i) h[i]=0;for(RI i=1;i<=n;++i) {int sz=a[i].size();if(sz<=2) {for(RI j=0;j<sz;++j)add(i,a[i][j],(a[i][j]<=kn)),add(a[i][j],i,(a[i][j]<=kn));}else {int o1=++n,o2=++n;v[o1]=v[o2]=v[i];add(i,o1,0),add(o1,i,0),add(i,o2,0),add(o2,i,0);for(RI j=0;j<sz;++j)if(j&1) a[o2].push_back(a[i][j]);else a[o1].push_back(a[i][j]);}}
}
void getrt(int x,int las,int SZ) {sz[x]=1;for(RI i=h[x];i;i=ne[i]) {if(vis[i>>1]||to[i]==las) continue;getrt(to[i],x,SZ),sz[x]+=sz[to[i]];int kl=max(sz[to[i]],SZ-sz[to[i]]);if(kl<mxx) mxx=kl,rt=i;}
}
void dfs2(int o,int x,int las,int len,int val) {val=min(val,v[x]),t[o][++js[o]]=(node){val,len};for(RI i=h[x];i;i=ne[i]) {if(vis[i>>1]||to[i]==las) continue;dfs2(o,to[i],x,len+d[i],val);}
}
void work(int x,int SZ) {mxx=inf,getrt(x,0,SZ);if(mxx==inf) return;int now=rt;vis[now>>1]=1;js[0]=js[1]=0,dfs2(0,to[now],0,0,inf),dfs2(1,to[now^1],0,0,inf);sort(t[0]+1,t[0]+js[0]+1,cmp),sort(t[1]+1,t[1]+js[1]+1,cmp);for(RI i=1,j=1,mxl=0;i<=js[0];++i) {while(j<=js[1]&&t[1][j].v>=t[0][i].v) mxl=max(mxl,t[1][j].len),++j;if(j!=1) ans=max(ans,1LL*t[0][i].v*(mxl+t[0][i].len+d[now]+1));}for(RI i=1,j=1,mxl=0;i<=js[1];++i) {while(j<=js[0]&&t[0][j].v>=t[1][i].v) mxl=max(mxl,t[0][j].len),++j;if(j!=1) ans=max(ans,1LL*t[1][i].v*(mxl+t[1][i].len+d[now]+1));}int ksz=sz[to[now]];work(to[now],ksz),work(to[now^1],SZ-ksz);
}
int main()
{int x,y;n=kn=read();for(RI i=1;i<=n;++i) v[i]=read();for(RI i=1;i<n;++i) x=read(),y=read(),add(x,y,1),add(y,x,1);dfs1(1,0),rebuild(),work(1,n);printf("%lld",ans);return 0;
}
边分治学习笔记(bzoj2870)相关推荐
- [摸鱼]cdq分治 学习笔记
待我玩会游戏整理下思绪(分明是想摸鱼 cdq分治是一种用于降维和处理对不同子区间有贡献的离线分治算法 对于常见的操作查询题目而言,时间总是有序的,而cdq分治则是耗费\(O(logq)\)的代价使动态 ...
- cdq分治 学习笔记
什么是 c d q cdq cdq 分治 一种很优美的分治,具体来说,我们解决 [ l , r ] [l,r] [l,r] 这个,跟普通的分治大体思路一样,也是先分治 [ l , m i d ] [l ...
- CDQ分治——学习笔记
前言 因为中国集训队的大佬们总会发明一些新的东西,所以中国的计算机竞赛水平才会一直处于国际前沿,而cdq分治也是某一年的集训队成员发明的算法. 什么是CDQ分治 cdq分治是一种分治(这不是废话嘛), ...
- [学习笔记]CDQ分治
分治,考虑前一半对后一半的影响. (和一般分治不太相同的思想是,一般分治不分谁对谁的影响,跨mid的都要统计.(全局变量统计) 而CDQ貌似要落脚到前一半对后一半的影响上,也就是贡献在后一半统计,由前 ...
- 【学习笔记】超简单的快速数论变换(NTT)(FFT的优化)(含全套证明)
整理的算法模板合集: ACM模板 目录 一.前置知识 二.快速数论变换(NTT) 三.NTT证明(和FFT的关系) 四.NTT模板 数组形式的实现 vector形式的实现 点我看多项式全家桶(●^◡_ ...
- 多项式相关操作学习笔记
多项式相关操作学习笔记 标签: 多项式 说在前边 记录一下相关的多项式操作,顺便存个模板.(多点求值之后的部分,有点写不动了...留坑留坑 多项式 定义 给定一个环\(R\)(\(R\)通常是交换环, ...
- K-D Tree 学习笔记
K-D Tree 学习笔记 最近看了一下k-NN然后它说如果特征空间维数比较低的时候用K-D Tree来求k近邻比较快所以就来补一下学OI时没学的K-D Tree假装写一个学习笔记吧. 是什么? 是一 ...
- 《数据结构与算法分析》学习笔记(二)——算法分析
一.对算法分析方法的最简单的理解和使用方法 1.首先大家可能一般会被那些数学的概念搞晕,其实简单理解下来,就是假设任何语句执行的效率都是一样的,所以设定每一个语句的执行时间都是一个时间单位,那么只要计 ...
- 快速傅里叶变换学习笔记(更新中)
快速傅里叶变换(FFT)学习笔记 简介 快速傅里叶变换($ \rm Fast Fourier Transformation $), 简称 \(\rm FFT\), 用于在 $ \Theta(n\log ...
最新文章
- python加载图片的方法_python从网络读取图片并直接进行处理的方法
- 当科学遇上众包:9个值得关注的前沿科技算力众包平台
- python10后的年利率_用Python把20年的GDP、人口以及房价数据进行了可视化
- react 不能往组件中传入属性的值为 undefined
- 设计模式整理之简单工厂
- react学习笔记(8)生命周期回顾与再认识
- Go的net/http
- c语言项开发班级登入系统,c语言--班级管理系统
- 特征工程系列学习(一)简单数字的奇淫技巧
- 【LeetCode】【HOT】287. 寻找重复数(抽象环形链表)
- python 优先队列_示例讲解:python队列原理及实现方法与操作思路
- mysql安装无法创建mysqld_MySQL 5.7安装错误`mysqld:无法创建/写入文件’/ var / lib / mysql / is_writable’...
- 刚刚用鸿蒙跑了个“hello world”!跑通后,我特么开始怀疑人生....
- CGAL几何库配置教程
- Delphi XE10.4字体字号对应的Font Size的点或像素换算
- Steam自建游戏服务器配置
- 小波包分解matlab程序
- 阿里巴巴java开发手册-泰山版 下载
- SpringBoot监控
- 云计算课程设计基于hadoop的词频统计设计