题目大意:给你一棵$n$个点的带权树和正整数$K$,求每个点到其它所有点距离中第$K$大的数值。

其中,边权$≤10000$,$n≤50000$。

我们通过原树构建一棵点分治树,令$fa[u]$为$u$在点分树上的$father$。

对于每个点$u$,我们维护两个有序数组$f$和$g$。

其中$f[i]$表示以$u$为根的点分树中,距离$u$第$i$近的距离。(显然里面有$siz[u]$个数值)

$g[i]$表示以$u$为根的点分树中,距离$fa[u]$第i近的距离。

我们二分答案,设当前二分到的值为$p$,我们要求所有与$u$距离$≤p$的数量。

然后答案显然为$\sum_{v∈ancestor[u]} (\sum_{f[v][i]≤p-dis(v,u)}1-\sum_{g[v][i]≤p-dis(fa[v],u)}1)$

这样单次询问的时间复杂度显然是$O(log^3n)$的。

然后时间复杂度就是$O(n\ log^3\ n)$。

完结撒花

 #include<bits/stdc++.h>
#define M 50005
#define INF 19890604
using namespace std; struct edge{int u,v,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
int n,k;
int f[M][]={},d[M]={},dep[M]={}; void dfs(int x,int fa){
f[x][]=fa; dep[x]=dep[fa]+;
for(int i=;i<;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
d[e[i].u]=d[x]+e[i].v;
dfs(e[i].u,x);
}
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y];
for(int i=;~i;i--) if((<<i)&cha) x=f[x][i];
for(int i=;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x==y) return x; return f[x][];
}
int getdis(int x,int y){
int lca=getlca(x,y);
return d[x]+d[y]-*d[lca];
} int vis[M]={},siz[M]={},minn=INF,minid=;
void dfssiz(int x,int fa){
siz[x]=;
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==){
dfssiz(e[i].u,x);
siz[x]+=siz[e[i].u];
}
}
void dfsmin(int x,int fa,int fsiz){
int maxn=fsiz-siz[x];
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==){
dfsmin(e[i].u,x,fsiz);
maxn=max(maxn,siz[e[i].u]);
}
if(maxn<minn) minn=maxn,minid=x;
}
int makeroot(int x){
dfssiz(x,);
minn=INF; minid=;
dfsmin(x,,siz[x]);
return minid;
}
vector<int> F[M],G[M]; void addvec(int x,int fa,int X,int FA,int nowdis){
F[X].push_back(getdis(x,X));
G[X].push_back(getdis(x,FA));
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==)
addvec(e[i].u,x,X,FA,nowdis+e[i].v);
}
int fa[M]={};
void build(int x,int Fa){
x=makeroot(x); vis[x]=; fa[x]=Fa;
addvec(x,fa[x],x,fa[x],);
sort(F[x].begin(),F[x].end());
sort(G[x].begin(),G[x].end());
for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==){
build(e[i].u,x);
}
} bool check(int x,int mid){
int res=-,X=x;
for(;x;x=fa[x]){ res+=upper_bound(F[x].begin(),F[x].end(),mid-getdis(X,x))-F[x].begin();
if(fa[x]) res-=upper_bound(G[x].begin(),G[x].end(),mid-getdis(X,fa[x]))-G[x].begin();
}
return res>=k;
} int main(){
scanf("%d%d",&n,&k);
for(int i=;i<n;i++){
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
dfs(,);
build(,);
for(int i=;i<=n;i++){
int l=,r=*n;
while(l<r){
int mid=(l+r)>>;
if(check(i,mid)) r=mid;
else l=mid+;
}
printf("%d\n",l);
}
}

【xsy1197】 树 二分+点分树+二分的更多相关文章

  1. 一篇自己都看不懂的点分治&点分树学习笔记

    淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...

  2. BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)

    题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...

  3. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  4. [CTSC2018]混合果汁(二分答案+主席树)

    考场上写了60分的二分答案,又写了15分的主席树,然后就弃了.. 合起来就A了啊!主席树忘了开20倍空间最后还炸掉了. 最水的签到题被我扔了,主要还是不会用线段树求前缀和. 做法应该是比较显然的,首先 ...

  5. 【Luogu】P2824排序(二分答案+线段树排序)

    题目链接 震惊!两个线段树和一个线段树竟是50分的差距! 本题可以使用二分答案,二分那个位置上最后是什么数.怎么验证呢? 把原序列改变,大于等于mid的全部变成1,小于mid的全部变成0,之后线段树排 ...

  6. cogs 2109. [NOIP 2015] 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分

    2109. [NOIP 2015] 运输计划 ★★★☆   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:3 s   内存限制:256 MB [题 ...

  7. Trace 2018徐州icpc网络赛 (二分)(树状数组)

    Trace There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx ...

  8. BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)

    某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...

  9. Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...

随机推荐

  1. pageX/pageY,screenX/screenY,clientX/clientY的差别

    pageX/pageY,screenX/screenY,clientX/clientY的差别 $(document).click(function(e){ //x方向无差别 //alert(e.pag ...

  2. Binary search tree or not

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  3. 让kbmmw 4.8 支持ios 64

    随着xe8 的出来,其开始支持IOS 64 的编译了(不支持也没办法,从今年2月开始不支持ios 64 的应用 就不允许入住apple appstore,霸气呀).相信不少同学迫不及待的开始了ios6 ...

  4. html零碎总结

    对于引用外部css时,格式是<link href="location" rel="stylesheet"/>,注意rel一定不能少且写成自闭合. 而 ...

  5. N个数的最大公约数

    #include <iostream> using namespace std; int main() { int c; ]={,,,}; ;i<;i++) { ]<m[i]) ...

  6. [翻译]Spring MVC RESTFul Web Service CRUD 例子

    Spring MVC RESTFul Web Service CRUD 例子 本文主要翻译自:http://memorynotfound.com/spring-mvc-restful-web-serv ...

  7. 几个CSS-content的小例子

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. EntityFramework 基本模式和Code-First的简单使用

    1.Database-First  Database First就是首先建立好数据库,或者存在现成的数据库也可以.然后在vs中添加ADO.Net实体数据模型,找到需要的数据库和表.它是以数据库设计为基 ...

  9. hbase使用MapReduce操作2(微博表实现)

    package com.yjsj.weibo; import java.io.IOException; import java.util.ArrayList; import java.util.Ite ...

  10. delphi 手机振动 IOS Android

    delphi 手机振动 IOS Android delphi  手机振动 IOS Android 振动 https://community.embarcadero.com/blogs/entry/ho ...