BZOJ3784树上的路径
题目描述
给定一个N个结点的树,结点用正整数1..N编号。每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路边上经过边的权值。其中要求a<b.将这n*(n-1)/2个距离从大到小排序,输出前M个距离值。
题解
把每次点分治时的dfs序写下来,假设我们在一个位置找能够和它拼成一条链的另一个位置,可以发现那些位置的顺序在dfs序上构成了一段连续区间,用ST表+堆维护。
注意在进队列之前先内啥一下。
代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#define N 50002
#define M 16
using namespace std;
int tot,head[N],lo[N*M],st[M][N*M],size[N],dp[N],sum,now,deep[N],root,n,p[M][N*M];
bool vis[N];
int start,ed;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l;}e[N<<];
inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}
struct node{
int now,l,r,sum;
node(int nownum=,int num1=,int num2=){
now=nownum;l=num1;r=num2;
int loo=lo[r-l+];
sum=now+max(st[loo][l],st[loo][r-(<<loo)+]);
}
int calc(){
int loo=lo[r-l+];
if(st[loo][l]>=st[loo][r-(<<loo)+])return p[loo][l];else return p[loo][r-(<<loo)+];
}
bool operator <(const node &b)const{return sum<b.sum;}
}pa[N*M];
priority_queue<node>q;
void getroot(int u,int fa){
size[u]=;dp[u]=;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;
getroot(v,u);
size[u]+=size[v];dp[u]=max(dp[u],size[v]);
}
dp[u]=max(dp[u],sum-size[u]);
if(dp[u]<dp[root])root=u;
}
void getsize(int u,int fa){
size[u]=;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;
getsize(v,u);
size[u]+=size[v];
}
}
void getdeep(int u,int fa){
st[][++now]=deep[u];p[][now]=now;
pa[now]=node(deep[u],start,ed);
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
deep[v]=deep[u]+e[i].l;
getdeep(v,u);
}
}
inline void calc(int u){
st[][++now]=;p[][now]=now;
pa[now]=node{,now,now};
start=now;ed=now;
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
deep[v]=e[i].l;
getdeep(v,u);
ed=now;
}
}
void solve(int u){
calc(u);vis[u]=;
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root=n+;sum=size[v];
getroot(v,u);getsize(root,);
solve(root);
}
}
int main(){
n=rd();int k=rd();int u,v,w;
for(int i=;i<n;++i){
u=rd();v=rd();w=rd();
add(u,v,w);add(v,u,w);
}
dp[root=n+]=n+;sum=n;
getroot(,);getsize(root,);
solve(root);
for(int i=;(<<i)<=now&&i<M;++i)
for(int j=;j+(<<i)-<=now;++j)
st[i][j]=max(st[i-][j],st[i-][j+(<<i-)]),p[i][j]=st[i-][j]>=st[i-][j+(<<i-)]?p[i-][j]:p[i-][j+(<<i-)];
for(int i=;i<=now;++i)lo[i]=lo[i>>]+;
for(int i=;i<=now;++i)pa[i]=node(pa[i].now,pa[i].l,pa[i].r),q.push(pa[i]);///care !!!!
for(int i=;i<=k;++i){
node x=q.top();q.pop();
printf("%d\n",x.sum);
int mid=x.calc();
if(x.l<mid)q.push(node(x.now,x.l,mid-));
if(x.r>mid)q.push(node(x.now,mid+,x.r));
}
return ;
}
BZOJ3784树上的路径的更多相关文章
- BZOJ3784 : 树上的路径
树的点分治,在分治的时候将所有点到根的距离依次放入一个数组q中. 对于一棵子树里的点,合法的路径一定是q[L]..q[R]的某个数加上自己到重心的距离. 定义五元组(v,l,m,r,w),表示当前路径 ...
- 2019.01.20 bzoj3784: 树上的路径(二分答案+点分治)
传送门 点分治好题. 题意简述:给一棵带边权的树,问所有路径中前mmm大的.m≤300000m\le300000m≤300000 思路: 网上有题解写了可以通过什么点分治序转化成超级钢琴那道题的做法蒟 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
- 【BZOJ-3784】树上的路径 点分治 + ST + 堆
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 462 Solved: 153[Submit][Status][Discuss ...
- codevs 2756树上的路径
题意: 2756 树上的路径 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树 ...
- bzoj 3784: 树上的路径 堆维护第k大
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 88 Solved: 27[Submit][Status][Discuss] ...
- 树上的路径 BZOJ 3784
树上的路径 [问题描述] 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a<b.将这n*(n-1)/2个距 ...
- Codevs 2756 树上的路径
2756 树上的路径 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树中存在 ...
- BZOJ3784:树上的路径
浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...
随机推荐
- 如何开启红米手机4X的ROOT超级权限
红米手机4X通过什么方法拥有了root权限?大家都清楚,Android机器有root权限,如果手机拥有了root相关权限,可以实现更强的功能,举个栗子大家公司的营销部门同事,使用大多数营销软件都需要在 ...
- Android 轮播图Banner切换图片的效果
Android XBanner使用详解 2018年03月14日 08:19:59 AND_Devil 阅读数:910 版权声明:本文为博主原创文章,未经博主允许不得转载. https://www. ...
- 关于JPasswordField的getText()方法过时问题解决
这几天想做一个登陆界面,用Jframe做,连接数据库时发现JPasswordField的getText()过时了,没法使用.查了资料发现改成了: try{ String sql="SELEC ...
- java基础知识总结二
1. synchronized和reentrantlock异同 相同点 都实现了多线程同步和内存可见性语义 都是可重入锁 不同点 实现机制不同 synchronized通过java对象头锁标记和Mon ...
- reStructuredText文件语法简单学习
reStructuredText 是一种扩展名为.rst的纯文本文件,通过特定的解释器,能够将文本中的内容输出为特定的格式 1. 章节标题 章节头部由下线(也可有上线)和包含标点的标题组合创建,其中下 ...
- MVC Controller return 格式分类及用法
概述 所看到的Action都是return View();我们可以看作这个返回值用于解析一个aspx文件.而它的返回类型是ActionResult如 public ActionResult Index ...
- .net DLL版本管理
每个DLL打上版本号,方便识别维护
- #021 Java复习第一天
上学期在慧河工作室学习简单过java到面向对象就停止了 现在有事情又要用到java发现全忘了..... 快速复习一下 网课PPT 计算机: 硬件 + 软件 主要硬件: cpu :cpu是一个计算机的运 ...
- Java程序设计与数据结构导论--读后感
与我前面所读的<Java7基础教程>相比,此书不适合自学,更适合作为教材使用. 虽然此书完整覆盖了Java的知识点和数据结构的基础问题,并且对每个部分都做了基本说明.但是因为没有深入展开, ...
- kernel笔记——块I/O
Linux下,I/O处理的层次可分为4层: 1. 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少 2. 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓 ...