2019.01.20 bzoj3784: 树上的路径(二分答案+点分治)
传送门
点分治好题。
题意简述:给一棵带边权的树,问所有路径中前mmm大的。m≤300000m\le300000m≤300000
思路:
网上有题解写了可以通过什么点分治序转化成超级钢琴那道题的做法蒟蒻吓得瑟瑟发抖。
然后由于我比较菜想了一个二分答案的方法。
我们二分第mmm大的值,每次用点分治检验合法性。
二分完了之后我们再跑一次点分统计答案。
然后第一个二分的时候直接做是logn3log^3_nlogn3的。
考虑降下来一个logloglog。
我们先dfsdfsdfs一次树把每个点作为重心的时候的所有distdistdist预处理下来就可以省掉一个logloglog啦! 空间复杂度O(nlogn)233
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=5e4+5,M=3e5+5;
int n,m,siz[N],msiz[N],stk[M],top=0,rt,all,Rt;
bool vis[N];
vector<pii>e[N];
vector<int>dis[N],g[N],inv[N];
ll ans;
priority_queue<int>ANS;
void getroot(int p,int fa){
siz[p]=1,msiz[p]=0;
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i].fi]||v==fa)continue;
getroot(v,p),siz[p]+=siz[v],msiz[p]=max(msiz[p],siz[v]);
}
msiz[p]=max(msiz[p],all-siz[p]);
if(msiz[p]<msiz[rt])rt=p;
}
void solve(int p,int fa,int dist,vector<int>&anc){
anc.push_back(dist);
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i].fi]||v==fa)continue;
solve(v,p,dist+e[p][i].se,anc);
}
}
void dfs(int p){
vis[p]=1,solve(p,0,0,dis[p]);
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i].fi])continue;
rt=0,all=siz[v],getroot(v,p),solve(v,p,e[p][i].se,inv[rt]),g[p].push_back(rt),dfs(rt);
}
}
inline ll calc(vector<int>&v,int lim){
ll ret=0;
for(ri i=0;i<v.size();++i)ret+=v.end()-lower_bound(v.begin(),v.end(),lim-v[i]);
return ret;
}
void Dfs(int p,int lim){
ans+=calc(dis[p],lim);
for(ri i=0;i<g[p].size();++i)ans-=calc(inv[g[p][i]],lim);
if(ans>=m)return;
for(ri i=0;i<g[p].size();++i)Dfs(g[p][i],lim);
}
inline bool check(int mid){return ans=0,Dfs(Rt,mid),ans>=m*2;}
void DFS(int p,int fa,int dist){
stk[++top]=dist;
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=fa&&!vis[v])DFS(v,p,dist+e[p][i].se);
}
inline void Solve(int p,int lim){
stk[top=1]=0;
for(ri i=0,len,v;i<e[p].size();++i){
if(vis[v=e[p][i].fi])continue;
len=top,DFS(v,p,e[p][i].se);
for(ri j=len+1,pos;j<=top;j++){
pos=lower_bound(stk+1,stk+len+1,lim-stk[j])-stk;
for(ri k=pos;k<=len;++k)ANS.push(stk[j]+stk[k]);
}
sort(stk+len+1,stk+top+1),inplace_merge(stk+1,stk+len+1,stk+top+1);
}
}
inline void ask(int p,int lim){vis[p]=1,Solve(p,lim);for(ri i=0;i<g[p].size();++i)ask(g[p][i],lim);}
int main(){
n=read(),m=read();
int L=0,R=0,K=0;
for(ri i=1,u,v,w;i<n;++i)u=read(),v=read(),w=read(),e[u].push_back(pii(v,w)),e[v].push_back(pii(u,w)),R+=w;
msiz[rt=0]=all=n,getroot(1,0),Rt=rt,dfs(Rt);
for(ri i=1;i<=n;++i)sort(dis[i].begin(),dis[i].end()),sort(inv[i].begin(),inv[i].end());
while(L<=R){
int mid=L+R>>1;
if(check(mid))K=mid,L=mid+1;
else R=mid-1;
}
memset(vis,0,sizeof(vis)),ask(Rt,K);
for(ri i=1;i<=m;++i){
if(ANS.size())cout<<ANS.top()<<'\n',ANS.pop();
else cout<<K<<'\n';
}
return 0;
}
2019.01.20 bzoj3784: 树上的路径(二分答案+点分治)的更多相关文章
- BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Submit: 1388 Solved: 860 [Submit][Stat ...
- 2019.03.04 bzoj5308: [Zjoi2018]胖(二分答案+st表)
传送门 想题5分钟调题两小时系列 其实还是我tcl 读完题之后自然会知道一个关键点能够更新的点是一段连续的区间,于是我们对于每个点能到的左右区间二分答案,用ststst表维护一下查询即可. 代码: # ...
- 洛谷P2680 运输计划 [LCA,树上差分,二分答案]
题目传送门 运输计划 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间, 这 n?1 条航道连通了 L 国的所 ...
- 2019.01.20 NOIP模拟 迅雷(kruskal/二分+并查集)
传送门 题意简述:给一张带权无向图,有a,ba,ba,b两类特殊点和普通点,问使得至少有一个aaa和一个bbb连通所需要的所有边边权最小值的最大值是多少. 思路: 一眼发现可以二分,考虑怎么check ...
- BZOJ3784 : 树上的路径
树的点分治,在分治的时候将所有点到根的距离依次放入一个数组q中. 对于一棵子树里的点,合法的路径一定是q[L]..q[R]的某个数加上自己到重心的距离. 定义五元组(v,l,m,r,w),表示当前路径 ...
- 2019.01.20 bzoj2238: Mst(kruskal+树链剖分)
传送门 树链剖分菜题. 题意简述:给一个无向图,边有边权,每次询问删一条边(对后面的询问无影响)之后的最小生成树. 思路: 先跑一次kruskalkruskalkruskal并把跑出来的最小生成树给链 ...
- 2019.01.20 bzoj2388: 旅行规划(分块+凸包)
传送门 分块好题. 题意:维护区间加,维护区间前缀和的最大值(前缀和指从1开始的). 思路: 考虑分块维护答案. 我们把每个点看成(i,sumi)(i,sum_i)(i,sumi)答案一定会在凸包上 ...
- 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)
传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
随机推荐
- nodejs中.npmrc文件的内容
. nodejs安装后,使用npm安装模块的时候我出现了一个错误. getaddrinfo ENOTFOUND xxx 主要是这个配置文件的问题.搞不清楚.直接打开把文件内容删除变成 npmrc文件内 ...
- 微信小程序开发——获取小程序带参二维码全流程
前言: 想要获取微信小程序带参数二维码,如这种: 官方文档只说了获取小程序码和二维码的三种接口及调用(参考链接:https://developers.weixin.qq.com/miniprogram ...
- eclipse项目运行文件位置
位置:E:\eclipseWorkSpace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\svnadmin
- MYSQL 优化常用方法总结
1, 选取最合适的字段属性以及长度 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快. 比如:定义邮政编码 char(6) 最合适,如果char(2 ...
- centos7下haproxy1.7的使用与配置
centos7下haproxy1.7的使用与配置 haproxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性.负载均衡,以及基于TCP和HTTP的应用程序代理. 一.haproxy下载 ...
- 手机端适配iPhoneX
iPhoneX取消了物理按键,改成底部小黑条,这一改动导致网页出现比较尴尬的屏幕适配问题.对于网页而言,顶部(刘海部位)的适配问题浏览器已经做了处理,所以我们只需要关注底部与小黑条的适配问题即可(即常 ...
- c# 策略模式 加工厂模式-对象与行为分离
计算器程序 策略模式是一种行为学模式.行为是同等级的算法 ,这些行为每个模式封装到一个类里 上端提供数据 ,下端提供算法 ,中间层context context 把上端的数据和算法 放到co ...
- IIS站点工作原理与ASP.NET工作原理
IIS站点工作原理与ASP.NET工作原理 一.IIS IIS 7.0工作原理图 两种模式: 1.用户模式(User Mode)(运行用户的程序代码.限制在特定的范围内活动.有些操作必须要受到Ker ...
- (转)Silverlight调用的JS方法返回对象数组的处理方法
最近在做Silverlight应用,需要用Silverlight调用页面中Javascript方法.这 个JS方法返回一个对象数组给Silverlight.对于这个对象数组怎么在Silverlight ...
- HDU_2112(最短路)
经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强.这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬 ...