题目描述

给定一个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=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x;
}
struct edge{int n,to,l;}e[N<<1];
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=0,int num1=0,int num2=0){now=nownum;l=num1;r=num2;int loo=lo[r-l+1];sum=now+max(st[loo][l],st[loo][r-(1<<loo)+1]);}int calc(){int loo=lo[r-l+1];if(st[loo][l]>=st[loo][r-(1<<loo)+1])return p[loo][l];else return p[loo][r-(1<<loo)+1];}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]=1;dp[u]=0;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]=1;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[0][++now]=deep[u];p[0][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[0][++now]=0;p[0][now]=now;pa[now]=node{0,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]=1;for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){int v=e[i].to;root=n+1;sum=size[v];getroot(v,u);getsize(root,0);solve(root);}
}
int main(){n=rd();int k=rd();int u,v,w;for(int i=1;i<n;++i){u=rd();v=rd();w=rd();add(u,v,w);add(v,u,w); }dp[root=n+1]=n+1;sum=n;getroot(1,0);getsize(root,0);solve(root);for(int i=1;(1<<i)<=now&&i<M;++i)for(int j=1;j+(1<<i)-1<=now;++j)st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]),p[i][j]=st[i-1][j]>=st[i-1][j+(1<<i-1)]?p[i-1][j]:p[i-1][j+(1<<i-1)];for(int i=2;i<=now;++i)lo[i]=lo[i>>1]+1;for(int i=1;i<=now;++i)pa[i]=node(pa[i].now,pa[i].l,pa[i].r),q.push(pa[i]);///care !!!!for(int i=1;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-1));if(x.r>mid)q.push(node(x.now,mid+1,x.r));}return 0;
} 

转载于:https://www.cnblogs.com/ZH-comld/p/10426934.html

BZOJ3784树上的路径相关推荐

  1. bzoj3784 树上的路径 点分治+RMQ+优先队列

    题目分析 树上的路径路径?可以,这很点分治. 求最长的mmm条的长度?可以,着很优先队列. 但问题是,用优先队列只能做全局才能保证复杂度是对的,但点分治是分治就不能做全局. 于是对于每次点分治,都记录 ...

  2. CodeForces - 1521D Nastia Plays with a Tree(树上最小路径覆盖)

    题目链接:点击查看 题目大意:给出一棵树,可以删除 xxx 条边并增加 xxx 条边使得树变为竹子,竹子就是一条链,问 xxx 最小可以为多少,输出一种方案数 题目分析:树上最小路径覆盖,按照子节点个 ...

  3. Codevs 2756 树上的路径

    2756 树上的路径  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树中存在路径P, ...

  4. [XSY3112] 接水果(树上包含路径,整体二分,扫描线)

    传送门 给出一棵nnn个点的树.接下来给出PPP条树上路径ai→bia_i\to b_iai​→bi​,及其权值cic_ici​.最后有QQQ个询问,每个询问给出一条树上路径ui→viu_i\to v ...

  5. 省选之前的未完成的计划(截至到省选)

    PLAN OF THE COMING HEOI good problems: -bzoj4823:[Cqoi2017]老C的方块 [*] -bzoj3171:[Tjoi2013]循环格 [*] -bz ...

  6. CF E2 - Daleks' Invasion (medium) (LCA求两点树上路径上的最大边权)

    http://codeforces.com/contest/1184/problem/E2 题意:给出一副图,首先求出这幅图的最小生成树 , 然后修改这幅图上不属于最小生成树的边权,使得修改后的图在求 ...

  7. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  8. 【jzoj5055】【GDOI2017模拟二试4.12】【树上路径】【点分治】

    题目大意 给定一颗n个结点的无根树,树上的每个点有一个非负整数点权,定义一条路径的价值为路径上的点权和-路径的点权最大值. 给定参数p,我们想知道,有多少不同的树上简单路径,满足它的价值恰好是p的倍数 ...

  9. JZOJ5055 树上路径

    Description 给定一颗n个结点的无根树,树上的每个点有一个非负整数点权,定义一条路径的价值为路径上的点权和-路径的点权最大值. 给定参数p,我们想知道,有多少不同的树上简单路径,满足它的价值 ...

最新文章

  1. 他,跳槽季用这样的方法复习进了阿里
  2. 170316.道格拉斯-普克算法
  3. vue中父组件怎么调用子组件
  4. MyBatis collection的两种形式——MyBatis学习笔记之九
  5. Nginx文档阅读笔记-DNS load balancing(DNS负载均衡)
  6. java token redis生成算法_Redis实现单点登录
  7. 有计算机考试励志的文案,关于考试的句子励志
  8. Insurance 项目——Mybetis-generator生成
  9. python基础运用_python基础----python的使用(三)
  10. HTG评论:Diamond WR300N无线中继器
  11. nn.functional.normalize
  12. ubuntu18.04安装kinect1(xbox360)驱动以及实时运行rtabmap
  13. MQTT与paho.mqtt
  14. CDN: trunk URL couldn‘t be downloaded的解决办法
  15. 什么是TRIZ理论?
  16. 10. 从0学ARM-基于Exynos4412的pwm详解
  17. 前端开发中常用的英语单词短语总结
  18. proteus教程——操作内存并行扩展8255
  19. 大数据开源平台好在哪里?
  20. 数据库课程设计作业报告

热门文章

  1. 用Java编写的密码翻译问题
  2. IPS与IDS部署场景(直路部署,单臂部署,旁路部署,阻断)
  3. DirtyCow漏洞复现(脏牛、大脏牛、Linux、Android、提权)
  4. C#删除字符串倒数第几个字符后的所有字符串
  5. python raise
  6. python实现根据经纬度画地图热力图
  7. AD服务器不愿意处理该请求
  8. 基础【枚举】-----(枚举)------(转)
  9. CanFestival移植准备工作
  10. STM32分散加载文件