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,使得,且在树中存在 ...
随机推荐
- 在一个JS文件中引用另一个JS文件
方法一,在调用文件的顶部加入下例代码: document.write(”<script language=javascript src=’/js/import.js’></scrip ...
- AWR元数据的迁移或导入到其它数据库
我们能够将AWR元数据迁移(导入)到其它数据库.低版本号的导入到高版本号,再用高版本号的数据库生成AWR报告,也能使用一些新特性,如 SQL ordered by Physical Reads (Un ...
- linux 设置静态IP方法
本系统使用 linux redhat 7.2 1. 修改ip vi /etc/sysconfig/network-scripts/ifcfg-eno16777736 2. 修改数据项如下 3. ...
- Windows上搭建Kafka
搭建环境: 1,安装JDK JAVA_HOME: C:\Program Files (x86)\Java\jre1.8.0_60(这个是默认安装路径,如果安装过程中更改了安装目录,把更改后的路径填上就 ...
- 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)
[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...
- android菜鸟学习笔记16----Android项目打包安装过程(Run as Android Application)
右击项目名称,Run as Android Appication之后,Android项目打包安装过程: 1.打包生成.apk文件: 1)把源码中的.java文件编译生成.class文件 2)将所有的. ...
- C#中GroupBox控件的使用(转)
GroupBox(框架)控件是C#中用来组织其他控件形成一个控件组,它的使用方法为[工具箱]->[所有Windows窗体](或者是[容器]列表中)->[GroupBox],拖拽到窗体界面中 ...
- centos7 执行一个数据库脚本创建项目中的数据库
[root@localhost ~]# su postgres 切换用户 bash-4.2$ psql could not change directory to "/root": ...
- curl下载安装
curl下载地址 https://curl.haxx.se/download.html 选择windows generic 下的 下载安装 安装完后解压配置系统环境变量 CURL_HOME ...
- NiFi汉化
①在源文件中的 source-nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src中修 ...