【BZOJ-3784】树上的路径 点分治 + ST + 堆
3784: 树上的路径
Time Limit: 10 Sec Memory Limit: 256 MB
Submit:
462 Solved: 153
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 2 1
1 3 2
2 4 3
2 5 4
Sample Output
7
6
5
4
4
3
3
2
1
HINT
N<=50000,M<=Min(300000,n*(n-1) /2
Source
Solution
超级钢琴推广到树上版本
利用点分治每个点的时间戳,将树转化到序列上,顺带记录每个节点,能和他组成一条路径的左右端点L,R
然后利用超级钢琴的方法去处理就好,具体见这里
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 100010
#define MAXM 1000100
int N,M;
struct EdgeNode{int next,to,val;}edge[MAXN<<];
int head[MAXN],cnt=;
void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
int maxx[MAXN],size[MAXN],Sz,root,L[MAXM],R[MAXM],D[MAXM],pl,pr,dfn;
bool visit[MAXN];
void DFSRoot(int now,int last)
{
size[now]=; maxx[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to])
{
DFSRoot(edge[i].to,now);
size[now]+=size[edge[i].to];
maxx[now]=max(maxx[now],size[edge[i].to]);
}
maxx[now]=max(maxx[now],Sz-size[now]);
if (maxx[now]<maxx[root]) root=now;
}
void Get(int x,int last,int Dis)
{
D[++dfn]=Dis; L[dfn]=pl,R[dfn]=pr;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to] && edge[i].to!=last)
Get(edge[i].to,x,Dis+edge[i].val);
}
void Divide(int x)
{
visit[x]=;
pl=pr=++dfn;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to]) Get(edge[i].to,x,edge[i].val),pr=dfn;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to])
{
Sz=size[edge[i].to]; root=;
DFSRoot(edge[i].to,x);
Divide(root);
}
}
int log2[MAXM],dp[][MAXM];
int Max(int x,int y) {return D[x]>D[y]? x:y;}
void ST()
{
log2[]=-;
for (int i=; i<=N; i++)
if (i&(i-)) log2[i]=log2[i-]; else log2[i]=log2[i-]+;
for (int i=; i<=dfn; i++) dp[][i]=i;
for (int j=; (<<j)<=dfn; j++)
for (int i=; i+(<<j)-<=dfn; i++)
dp[j][i]=Max(dp[j-][i],dp[j-][i+(<<j-)]);
}
inline int RMQ(int l,int r)
{
int tmp=log2[r-l+];
return Max(dp[tmp][l],dp[tmp][r-(<<tmp)+]);
}
struct HeapNode
{
int ip,L,R,pos;
HeapNode (int ip=,int L=,int R=,int pos=)
: ip(ip),L(L),R(R),pos(pos) {}
bool operator < (const HeapNode & A) const
{return D[ip]+D[pos]<D[A.ip]+D[A.pos];}
};
priority_queue<HeapNode>heap;
int main()
{
N=read(),M=read();
for (int x,y,z,i=; i<=N-; i++) x=read(),y=read(),z=read(),InsertEdge(x,y,z);
maxx[root=]=Sz=N;
DFSRoot(,);
Divide(root);
ST();
for (int i=; i<=dfn; i++)
heap.push( HeapNode(i,L[i],R[i],RMQ(L[i],R[i])) );
while (M--)
{
HeapNode now=heap.top(); heap.pop();
printf("%d\n",D[now.ip]+D[now.pos]);
HeapNode ls=now; ls.R=now.pos-;
if (ls.R>=ls.L) ls.pos=RMQ(ls.L,ls.R),heap.push(ls);
HeapNode rs=now; rs.L=now.pos+;
if (rs.R>=rs.L) rs.pos=RMQ(rs.L,rs.R),heap.push(rs);
}
return ;
}
一天前刚写超级钢琴,写起来就非常顺畅了
【BZOJ-3784】树上的路径 点分治 + ST + 堆的更多相关文章
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- BZOJ 3784: 树上的路径 点分治+二分+set
很容易想出二分这个思路,但是要想办法去掉一个 $log$. 没错,空间换时间. 双指针的部分错了好几次~ Code: #include <set> #include <queue&g ...
- bzoj 3784: 树上的路径 堆维护第k大
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 88 Solved: 27[Submit][Status][Discuss] ...
- bzoj 3784: 树上的路径【点分治+st表+堆】
参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
- BZOJ 3784: 树上的路径
Description 问一棵树上前 \(k\) 大路径的边权. Sol 边分治. 非常感谢数据没有菊花图. 为了写写边分治试试然后就开了这道题. 边分治非常好想,选一条重边,分成两部分,然后分别求最 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
- BZOJ 1316: 树上的询问( 点分治 + 平衡树 )
直接点分治, 用平衡树(set就行了...)维护. -------------------------------------------------------------------------- ...
- BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]
传送门 题意: 路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段 第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学 昨天两 ...
- BZOJ 3697: 采药人的路径 点分治
好久不做点分治的题了,正好在联赛之前抓紧复习一下. 先把边权为 $0$ 的置为 $-1$.定义几个状态:$f[dis][0/1],g[dis][0/1]$ 其中 $f$ 代表在当前遍历的子树内的答案. ...
随机推荐
- Centos5.8 安装openvpn
安装openssl 和 openssl-devel, 建议使用最新版本, 编译安装 yum install gcc-c++ wget http://www.openssl.org/source/ope ...
- PAT 1027. 打印沙漏(20)
本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个"*",要求按下列格式打印 ***** *** * *** ***** 所谓"沙漏形状",是指每行 ...
- 031医疗项目-模块三:药品供应商目录模块——供货商药品目录查询功能----------sql补充知识
这个补充知识有一个点很有必要,视屏上的老师提出一点: 内链接关联查询: 如果表A和表B有一个外键关联 ,可以通过外键进行内链接查询 select dictinfo.*, dicttype.typena ...
- .NET Core)的ZooKeeper异步客户端
支持断线重连.永久watcher.递归操作并且能跨平台(.NET Core)的ZooKeeper异步客户端 阅读目录 什么是ZooKeeper? 项目介绍 提供的功能 使用说明 FAQ 在公司内部 ...
- Linux 守护进程三
.打开telnet工具,登录服务器,登录校验成功以后, linux服务器会在终端和服务器之间,建立一个会话期session .在这个会话期中,默认启动一个shell程序 .在会话期中有n个进程组 sh ...
- 拒绝了对对象 'XXX' (数据库 'XXX',架构 'dbo')的 SELECT 权限
2010-04-17 23:16 在IIS里测试ASP.NET网站时会遇到这样的问题(ASP.NET+SQL2005)我自己的解决方法是这样的: 1.打开SQL2005管理界面(没有安装SQLServ ...
- PRML读书会第十三章 Sequential Data(Hidden Markov Models,HMM)
主讲人 张巍 (新浪微博: @张巍_ISCAS) 软件所-张巍<zh3f@qq.com> 19:01:27 我们开始吧,十三章是关于序列数据,现实中很多数据是有前后关系的,例如语音或者DN ...
- Paris Traceroute
Paris Traceroute is a new version of the well-known network diagnosis and measurement tool. Why shou ...
- [转]7个高性能JavaScript代码高亮插件
对于喜欢写技术博客的同学来说,一定对代码高亮组件非常熟悉.一款优秀的JavaScript代码高亮插件,将会帮助你渲染任何一种编程语言,包括一些关键字的着色,以及每行代码的缩进等.今天我们要来分享一些高 ...
- Php 安装 curl
一.用好tab键.输入一部分,就按两次tab键,看看到底应该安什么