树上的路径 BZOJ 3784
树上的路径
【问题描述】
【输入格式】
【样例输入】
5 10
1 2 1
1 3 2
2 4 3
2 5 4
【样例输出】
7
7
6
5
4
4
3
3
2
1
【数据范围】
N<=50000,M<=Min(300000,n*(n-1) /2 )
题解:
考虑将点分治时访问的点的顺序作为一个序列
每个位置都有其对应的区间(指向这个位置所在重心树访问的前面所有子树,那么这就代表了这个位置对应的点出发经过这个重心的所有路径)
那么原问题转化为了BZOJ 2006 超级钢琴的问题
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf = ;
const int logn = ;
const int logs = ;
const int maxn = 5e4 + ;
const int maxm = maxn << ;
const int maxs = maxn * logn + ;
inline void Scan(int &x)
{
char c;
bool o = false;
while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
x = c - '';
while(isdigit(c = getchar())) x = x * + c - '';
if(o) x = -x;
}
int tot, nex[maxm], ver[maxm], fir[maxn], val[maxm];
inline void Ins(int x, int y, int z)
{
nex[++tot] = fir[x];
fir[x] = tot;
ver[tot] = y;
val[tot] = z;
}
int sum, root;
int size[maxn], heavy[maxn];
bool vis[maxn];
void Getroot(int u, int f)
{
heavy[u] = ;
size[u] = ;
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f || vis[v]) continue;
Getroot(v, u);
size[u] += size[v];
heavy[u] = max(heavy[u], size[v]);
}
heavy[u] = max(heavy[u], sum - size[u]);
if(heavy[u] < heavy[root]) root = u;
}
struct couple
{
int l, r;
};
couple c[maxs];
int num, l, r;
int dis[maxn], len[maxs];
int big[logs][maxs];
void Getdis(int u, int f)
{
len[++num] = dis[u], big[][num] = num;
c[num] = (couple) {l, r};
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f || vis[v]) continue;
dis[v] = dis[u] + val[i];
Getdis(v, u);
}
}
void Div(int u)
{
root = ;
Getroot(u, );
l = r = ++num;
len[num] = , big[][num] = num;
vis[root] = true;
for(int i = fir[root]; i; i = nex[i])
{
int v = ver[i];
if(vis[v]) continue;
dis[v] = val[i];
Getdis(v, root);
r = num;
}
for(int i = fir[root]; i; i = nex[i])
{
int v = ver[i];
if(vis[v]) continue;
sum = size[v];
Div(v);
}
}
inline int Max(int a, int b)
{
return (len[a] > len[b]) ? a : b;
}
int bin[logs], lg[maxs];
inline void Rmq()
{
int lgn = log2(num);
bin[] = ;
for(int i = ; i <= lgn; ++i) bin[i] = bin[i - ] << , lg[bin[i]] = ;
for(int i = ; i <= num; ++i) lg[i] += lg[i - ];
for(int k = ; k <= lgn; ++k)
for(int i = ; i <= num; ++i)
{
if(i + bin[k] - > num) continue;
int j = i + bin[k - ];
big[k][i] = Max(big[k - ][i], big[k - ][j]);
}
}
inline int Query(int l, int r)
{
if(l > r) return -;
int len = lg[r - l + ];
return Max(big[len][l], big[len][r - bin[len] + ]);
}
int n, m;
struct interval
{
int l, r, a, b, v;
};
inline bool operator < (interval a, interval b)
{
return a.v < b.v;
}
priority_queue <interval> q;
int main()
{
Scan(n), Scan(m);
int a, b;
for(int i = ; i < n; ++i)
{
int c;
Scan(a), Scan(b), Scan(c);
Ins(a, b, c), Ins(b, a, c);
}
sum = n;
root = ;
heavy[] = inf;
Div();
Rmq();
int x;
for(int i = ; i <= num; ++i)
{
a = c[i].l, b = c[i].r;
if(a)
{
x = Query(a, b);
q.push((interval) {a, b, i, x, len[i] + len[x]});
}
}
int u, v;
interval s;
while(m--)
{
s = q.top(), q.pop();
u = Query(s.l, s.b - );
v = Query(s.b + , s.r);
if(u > ) q.push((interval) {s.l, s.b - , s.a, u, len[u] + len[s.a]});
if(v > ) q.push((interval) {s.b + , s.r, s.a, v, len[v] + len[s.a]});
printf("%d\n", s.v);
}
}
树上的路径 BZOJ 3784的更多相关文章
- bzoj 3784: 树上的路径 堆维护第k大
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 88 Solved: 27[Submit][Status][Discuss] ...
- 【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,使得,且在树 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
- Codevs 2756 树上的路径
2756 树上的路径 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树中存在 ...
- BZOJ 3784: 树上的路径
Description 问一棵树上前 \(k\) 大路径的边权. Sol 边分治. 非常感谢数据没有菊花图. 为了写写边分治试试然后就开了这道题. 边分治非常好想,选一条重边,分成两部分,然后分别求最 ...
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- bzoj 3784: 树上的路径【点分治+st表+堆】
参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
- BZOJ 3784: 树上的路径 点分治+二分+set
很容易想出二分这个思路,但是要想办法去掉一个 $log$. 没错,空间换时间. 双指针的部分错了好几次~ Code: #include <set> #include <queue&g ...
随机推荐
- javaweb基础(11)_cookie的会话管理
一.会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾 ...
- ASP.NET WebApi 路由配置
ASP.NET Web API路由是整个API的入口.我们访问某个资源就是通过路由映射找到对应资源的URL.通过URL来获取资源的. 对于ASP.NET Web API内部实现来讲,我们的请求最终将定 ...
- CocoaPods在OS X Yosemite上突然不能用了的解决办法
最近开发的时候发现自己的CocoaPods不能使用了! 根据报的错误上网搜寻answer,于是搜到了解决办法 在 OS X Yosemite 报这样的错: [MT] DVTAssertions: AS ...
- ReactiveCocoa入门-part2
ReactiveCocoa是一个框架,它能让你在iOS应用中使用函数响应式编程(FRP)技术.在本系列教程的第一部分中,你学到了如何将标准的动作与事件处理逻辑替换为发送事件流的信号.你还学到了如何转换 ...
- 如何用VS2017用C++语言写Hello world 程序?
1,首先,打开VS2017. 2,左上角按文件——新建——项目,或按ctrl+shift+n. 3,按照图片里的选,选完按“确定”. 4,右键“源文件”,再按添加——新建项. 5,剩下的就很简单了,只 ...
- tensorflow目标检测API之训练自己的数据集
1.训练文件的配置 将生成的csv和record文件都放在新建的mydata文件夹下,并打开object_detection文件夹下的data文件夹,复制一个后缀为.pbtxt的文件到mtdata文件 ...
- [LUOGU] P4251 [SCOI2015]小凸玩矩阵
行列看成点,格子看成边,二分一个边权,删去大于它的边,新图上的最大流>k则答案可以更优,小于k则调整左边界. #include<algorithm> #include<iost ...
- C#基础-数组-ArrayList
数组ArrayList using System.Collections; //表示引入集合的命名空间 数组ArrayList容量本身是不固定的,根据存储的数据动态变化 // 声明一个ArrayLis ...
- javascript实现原生ajax的几种方法介绍
自从javascript有了各种框架之后,比如jquery,使用ajax已经变的相当简单了.但有时候为了追求简洁,可能项目中不需要加载jquery这种庞大的js插件.但又要使用到ajax这种功能该如何 ...
- memcache 协议 && Golang实现
https://github.com/quguolin/memcache 一:Error ERROR\r\n 客户端发送了一个不存在的命令 CLIENT_ERROR\r\n 客户端发送了一个不符合协议 ...