bzoj 2870 最长道路tree——边分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2870
关于边分治:https://www.cnblogs.com/Khada-Jhin/p/10154994.html
自己写了那种把一个孩子连向自己,其他孩子连新建节点的重构图方法。
如果 vector 里最后一个元素恰好是父亲的话,末尾就会有一个新建节点只有一个孩子。
solve( ) 完之后要继续 get_rt( ) ,想知道两边的点数 ts ;可以发现 to[ cr ] 的部分点数恰好是 siz[ to[ cr ] ] ,另一部分就是 s - siz[ to[ cr ] ] 了。
要递归的时候,如果 ts == 1 ,就不递归了。
关于这道题:https://www.cnblogs.com/Miracevin/p/10430192.html
虚点的点权就是它建出它的那个实点的点权;路径上的点数等于路径上的实边条数 + 1 。
找出两边的路径,分别 sort 然后双指针即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
ll Mx(ll a,ll b){return a>b?a:b;}
ll Mn(ll a,ll b){return a<b?a:b;}
const int N=5e4+,M=N<<,INF=7e4;
int n,vl[M],hd[M],xnt=,to[M<<],nxt[M<<],w[M<<];//xnt=1
int siz[M],mn,Rt,tot[]; bool vis[M]; ll ans;
vector<int> vt[N];
struct Node{
int dis,mn;
Node(int d=,int m=):dis(d),mn(m) {}
bool operator< (const Node &b)const
{return mn<b.mn;}
}a[][M];
void add(int x,int y,int z)
{
to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;
to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;w[xnt]=z;
}
void Rbuild(int cr,int fa)
{
for(int i=,lm=vt[cr].size()-,v,lst=;i<=lm;i++)
{
if((v=vt[cr][i])==fa)continue;
if(!lst) add(cr,v,), lst=cr;
else if(i==lm) add(lst,v,);
else
{
n++; vl[n]=vl[cr];
add(lst,n,); add(n,v,); lst=n;
}
}
for(int i=,lm=vt[cr].size(),v;i<lm;i++)
if((v=vt[cr][i])!=fa)Rbuild(v,cr);
}
void get_rt(int cr,int fa,int s)
{
siz[cr]=;
for(int i=hd[cr],v,d;i;i=nxt[i])
if(!vis[i>>]&&(v=to[i])!=fa)
{
get_rt(v,cr,s); siz[cr]+=siz[v];
d=Mx(siz[v],s-siz[v]);
if(d<mn)mn=d, Rt=i;
}
}
void dfs(int cr,int fa,int lj,int mn,bool fx)
{
mn=Mn(mn,vl[cr]); a[fx][++tot[fx]]=Node(lj,mn);
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[i>>]&&(v=to[i])!=fa)
dfs(v,cr,lj+w[i],mn,fx);
}
void cz()
{
for(int i=;i<=;i++)
sort(a[i]+,a[i]+tot[i]+);
int p0=tot[]+, lj=, tw=w[Rt]+;//+1
for(int i=tot[];i;i--)
{
int tmn=a[][i].mn;
while(p0>&&a[][p0-].mn>=tmn)
p0--, lj=Mx(lj,a[][p0].dis);
if(p0>tot[])continue;//
ans=Mx(ans,(ll)tmn*(lj+a[][i].dis+tw));
}
p0=tot[]+; lj=;
for(int i=tot[];i;i--)
{
int tmn=a[][i].mn;
while(p0>&&a[][p0-].mn>=tmn)
p0--, lj=Mx(lj,a[][p0].dis);
if(p0>tot[])continue;//
ans=Mx(ans,(ll)tmn*(lj+a[][i].dis+tw));
}
}
void solve(int cr,int s)
{
vis[cr>>]=;
tot[]=tot[]=;
dfs(to[cr],,,INF,); dfs(to[cr^],,,INF,);
cz();
int v=to[cr], ts=siz[v];
if(ts>){mn=N; get_rt(v,,ts); solve(Rt,ts);}
ts=s-ts; v=to[cr^];// s-ts not s-siz[v] for siz[v] may changed!!!
if(ts>){mn=N; get_rt(v,,ts); solve(Rt,ts);}
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)vl[i]=rdn();
for(int i=,u,v;i<n;i++)
{
u=rdn();v=rdn(); vt[u].pb(v); vt[v].pb(u);
}
Rbuild(,);
mn=N;get_rt(,,n);solve(Rt,n);
printf("%lld\n",ans);
return ;
}
bzoj 2870 最长道路tree——边分治的更多相关文章
- BZOJ 2870: 最长道路tree 树的直径+并查集
挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...
- 【BZOJ2870】最长道路tree 点分治+树状数组
[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...
- bzoj2870最长道路tree——边分治
简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 有几个不同的做法: 1.sort+并查集+树的直径.边从大到小加入 ...
- 2870: 最长道路tree
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2870 思路 先把树转化为二叉树 再链分治 %%yyb 代码 #include <ios ...
- 【BZOJ2870】最长道路(边分治)
[BZOJ2870]最长道路(边分治) 题面 BZOJ权限题 Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样 ...
- BZOJ2870—最长道路tree
最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都 ...
- 【bzoj 2870】 最长道路tree
题目 边分治 边分和点分相比就是找到一条重心边,考虑所有经过这条边的路径,之后断开这条边分成两个联通块,继续分治 由于每次分治重心是一条边,所以只会产生两个联通块,考虑两个联通块显然要比像点分那样考虑 ...
- [BZOJ2870]最长道路tree:点分治
算法一:点分治+线段树 分析 说是线段树,但是其实要写树状数组卡常. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(register ...
- BZOJ2870: 最长道路tree
题解: 子树分治的做法可以戳这里:http://blog.csdn.net/iamzky/article/details/41120733 可是码量... 这里介绍另一种好写又快的方法. 我们还是一颗 ...
随机推荐
- Tensorflow函数:tf.zeros
tf.zeros函数 tf.zeros( shape, dtype=tf.float32, name=None ) 定义在:tensorflow/python/ops/array_ops.py. 创建 ...
- MySQL:安装mysqld系统及基础应用
MySQL篇 第一章.安装mysqld系统及基础应用 一.安装 注意:mysql的标点符号只能是英文的标点符号. 1.设置配置文件. 文件格式:文本格式 文件位置:Mysql的主目录下 文件名称:my ...
- Flask源码阅读-第一篇(flask包下的__main__.py)
源码: # -*- coding: utf-8 -*-""" flask.__main__ ~~~~~~~~~~~~~~ Alias for flask.run for ...
- python3自学第二天,模块,三元运算
1.模块的认识. sys模块,os模块等 如何引入模块 import os cmd_res1=os.system("dir") # 执行命令dir,不保存结果 print(cmd_ ...
- redis 基础应用
redis 安装 -redis安装 -window的安装 -redis支持5大数据类型 -字符 Memcached 只支持字符串类型 -列表 -字典 -集合 -有序集合 面试题:游戏 ...
- python 异常处理函数--raise
Python 异常处理--raise函数用法 在Python中,要想引发异常,最简单的形式就是输入关键字raise,后跟要引发的异常的名称.异常名称标识出具体的类: Python异常处理是那些类的对象 ...
- linux系统nginx的https的跳转
环境:系统ubuntu16 申请证书是腾讯云免费证书 首先我在安装nginx SSL证书的时候犯了个错误,nginx是需要安装SSl的模块不然没法配置完成.需要安装一个 http_ssl_module ...
- Gym 101889:2017Latin American Regional Programming Contest(寒假自训第14场)
昨天00.35的CF,4点才上床,今天打的昏沉沉的,WA了无数发. 题目还是满漂亮的. 尚有几题待补. C .Complete Naebbirac's sequence 题意:给定N个数,他们在1到K ...
- Gym.102059: 2018-2019 XIX Open Cup, Grand Prix of Korea(寒假gym自训第一场)
整体来说,这一场的质量比较高,但是题意也有些难懂. E.Electronic Circuit 题意: 给你N个点,M根线,问它是否是一个合法的电路. 思路: 一个合法的电路,经过一些串联并联关系, ...
- win10 ubuntu 同一硬盘双系统安装和启动设置
1.了解启动的顺序 电脑开机---> BIOS 设置 ----> 硬盘(MBR)/ GPT格式里的ESP分区 ---> (UEFI/GRUB)目录里的 *****.efi -- ...