题目大意:给你一棵$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. 一款非常好用的boostrap的验证插件、再也不用自己手写正则表达式和js了

    基于jquery.bootstrap数据验证插件bootstrapValidator教程 bootstrap:能够增加兼容性的强大框架. 因为项目需要数据验证,看bootstrapValidator ...

  2. python私有公有属性

    python中,类内方法外的变量叫属性,类内方法内的变量叫字段.他们的私有公有访问方法类似. class C: __name="私有属性" def func(self): prin ...

  3. Field '***********' doesn't have a default value

    今天做配置文件一直报这个错误: 原因是主键是integer类型,没有设置自增模式,所以会出现这个问题,是表的结构问题.更改用navicat

  4. 做MFC的时候引用了头文件但VC还是报missing storage-class or type specifiers

    我在客户端clg.h头文件中引用了头文件“ClientSocket.h”,然后在客户端clg.h中的类中声明了类CClientSocket的对象,可是编译报错:d:\vc++\客户端\客户端dlg.h ...

  5. Object-C中 - self 和super 的含义

    //super:父类         //self:自己              //自己理解         //以MobilePhone为例,父类为NSObject         //在类方法 ...

  6. (转)SQL Server 2008无法修改表的解决办法

    转自:http://www.soaspx.com/dotnet/sql/mssql/sql2008/sqlserver2008_20121010_9683.html 在SQL Server 2008 ...

  7. 利用Project Tango进行室内三维建模 精度评定

    coming soon 在Android开发基础上开发Tango应用 Android+Tango

  8. noip第10课作业

    1.     统计不同类型字符出现次数 [问题描述] 输入一个字符串(假设长度不超过1000个字符),统计其中大写,小写,数字,其他字符出现的次数. [样例输入]Hello,what are you ...

  9. hdu4417(Super Mario)—— 二分+划分树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  10. uploadify的碎碎念 upload

    uploadify是一个jquery插件,用来实现文件上传的功能. 20160724 看起来感觉挺麻烦的 一般会买一个html5版的. html <input id="custom_f ...