BZOJ3784:树上的路径
浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3784
难得地看了题解,发现居然还有点分序这么个玩意儿……
对于点分治时遍历过的点的长度为\(nlogn\)的序列,我们称它为点分序。
然后这题就是树上超级钢琴,在点分序上做就行了。对于每一条边,在点分序里能与其匹配的边是一段区间。
时间复杂度:\(O(nlogn*(1+log(nlogn)))\)
空间复杂度:\(O(nlogn*log(nlogn))\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=5e4+5;
bool vis[maxn];
int n,m,mx,rt,N,tot,cnt,L,R;
int now[maxn],pre[maxn*2],son[maxn*2],val[maxn*2];
int siz[maxn],a[maxn*20],Log[maxn*20],f[20][maxn*20];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
void add(int a,int b,int c) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b,val[tot]=c;
}
struct node {
int v,pos,l,r;
node() {}
node(int _v,int _pos,int _l,int _r) {
v=_v,pos=_pos,l=_l,r=_r;
}
bool operator<(const node &a)const {
return v<a.v;
}
};
struct Heap {
int tot;
node tree[maxn*26];
void ins(node res) {
tree[++tot]=res;
int pos=tot;
while(pos>1) {
if(tree[pos>>1]<tree[pos])
swap(tree[pos>>1],tree[pos]),pos>>=1;
else break;
}
}
node pop() {
node res=tree[1];
tree[1]=tree[tot--];
int pos=1,son=2;
while(son<=tot) {
if(son<tot&&tree[son]<tree[son|1])son|=1;
if(tree[pos]<tree[son])
swap(tree[son],tree[pos]),pos=son,son=pos<<1;
else break;
}
return res;
}
}T;
void find_rt(int fa,int u) {
int res=0;siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)find_rt(u,v),siz[u]+=siz[v],res=max(res,siz[v]);
res=max(res,N-siz[u]);
if(res<mx)mx=res,rt=u;
}
void solve(int fa,int u,int dis) {
a[++cnt]=dis;T.ins(node(a[mx]+dis,cnt,L,R)),siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)solve(u,v,dis+val[p]),siz[u]+=siz[v];
}
void work(int u,int size) {
N=size,mx=rt=n+1,find_rt(0,u);
u=rt,vis[u]=1,a[++cnt]=0,L=cnt,mx=cnt;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]) {
R=cnt,solve(u,v,val[p]);
for(int j=R+1;j<=cnt;j++)
if(a[j]>a[mx])mx=j;
}
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v])work(v,siz[v]);
}
int fake(int num1,int num2) {
if(a[num1]>a[num2])return num1;
return num2;
}
int query(int l,int r) {
int x=Log[r-l+1];
return fake(f[x][l],f[x][r-(1<<x)+1]);
}
void make_st() {
Log[0]=-1;
for(int i=1;i<=cnt;i++)
f[0][i]=i,Log[i]=Log[i>>1]+1;
for(int i=1;i<=19;i++)
for(int j=1;j+(1<<i)-1<=cnt;j++)
f[i][j]=fake(f[i-1][j],f[i-1][j+(1<<(i-1))]);
}
int main() {
n=read(),m=read();
for(int i=1;i<n;i++) {
int a=read(),b=read(),c=read();
add(a,b,c),add(b,a,c);
}work(1,n),make_st();
for(int i=1;i<=m;i++) {
node tmp=T.pop();
int pos=query(tmp.l,tmp.r);
if(pos-1>=tmp.l)
T.ins(node(a[query(tmp.l,pos-1)]+a[tmp.pos],tmp.pos,tmp.l,pos-1));
if(pos+1<=tmp.r)
T.ins(node(a[query(pos+1,tmp.r)]+a[tmp.pos],tmp.pos,pos+1,tmp.r));
printf("%d\n",tmp.v);
}
return 0;
}
BZOJ3784:树上的路径的更多相关文章
- BZOJ3784 : 树上的路径
树的点分治,在分治的时候将所有点到根的距离依次放入一个数组q中. 对于一棵子树里的点,合法的路径一定是q[L]..q[R]的某个数加上自己到重心的距离. 定义五元组(v,l,m,r,w),表示当前路径 ...
- 2019.01.20 bzoj3784: 树上的路径(二分答案+点分治)
传送门 点分治好题. 题意简述:给一棵带边权的树,问所有路径中前mmm大的.m≤300000m\le300000m≤300000 思路: 网上有题解写了可以通过什么点分治序转化成超级钢琴那道题的做法蒟 ...
- BZOJ3784树上的路径
题目描述 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a<b.将这n*(n-1)/2个距离从大到小排序, ...
- 【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,使得,且在树中存在 ...
随机推荐
- 浅谈 Fork/Join
fork/join的java7新添加的功能,能够把它理解成一个并发框架. 我们通过fork/join能将一个可分解的大任务.分解成多个子任务同步运行.运行完成后,在将各子任务的结果进行合并,得到终于的 ...
- easyUI中 datagrid 一列字比较多时,出现省略符号
当数据比较多为,出现省略符号 <style type="text/css"> .datagrid-cell, .datagrid-cell-gro ...
- JavaScript -- 没事看看
@.delete 原文:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete
- java 多参实现
package com.northeasttycoon.monitor.service; import static java.lang.System.out; /** * Created by no ...
- activemq 安装-单点
一,准备工作:首先安装jdk1.7及其以上版本,此环境安装的是jdk-1.8 二.搭建activemq 环境: 192.168.9.25 centos6.5 ...
- 【BZOJ4619/3709】[Wf2016]Swap Space/[PA2014]Bohater 贪心
[BZOJ4619][Wf2016]Swap Space Description 你有许多电脑,它们的硬盘用不同的文件系统储存数据.你想要通过格式化来统一文件系统.格式化硬盘可能使它的容量发生变化.为 ...
- SQL 经验总结
总结日常工作中使用SQL遇到的坑和技巧,一是加深印象,二是方便回顾.会不定期更新. 坑 1.多表联查时要使用表名,如果两个表的有列名相同的情况你没有加别名,那么sql编译器就不知道使用哪个列.这时进行 ...
- 我的Java开发学习之旅------>Java String对象作为参数传递的问题解惑
又是一道面试题,来测试你的Java基础是否牢固. 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) ...
- Objective-c中的delegate浅析
delegate初探 在ios开发中,我们常常会用到类似例如以下的对话框: 因此,例如以下这段代码我们也就非常熟悉了: - (IBAction)showSheet:(id)sender { UIAct ...
- 硬分叉后,BCH的钱包解决方案
上周BCH进行了硬分叉,分叉成了两条链:BCH和BCHSV,对于分叉后的BCH如何进行交易呢?钱包是否有相关的危险因素? 由于分叉后的两条链没做重放保护,可能导致一条链上发起的交易,在另一条链上做重放 ...