很容易想出二分这个思路,但是要想办法去掉一个 $log$.

没错,空间换时间.

双指针的部分错了好几次~

Code:

  1. #include <set>
  2. #include <queue>
  3. #include <cstdio>
  4. #include <vector>
  5. #include <algorithm>
  6. #define N 2000003
  7. #define ll long long
  8. #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
  9. using namespace std;
  10. ll answer;
  11. priority_queue<int>q;
  12. vector<int>G[N],F[N],go[N];
  13. int edges,n,root,sn,tmp,len,tt,m,flag;
  14. int hd[N],nex[N<<1],to[N<<1],val[N<<1];
  15. int size[N],mx[N],vis[N];
  16. bool cmp(int a,int b)
  17. {
  18. return a>b;
  19. }
  20. void add(int u,int v,int c)
  21. {
  22. nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
  23. }
  24. void getroot(int u,int ff)
  25. {
  26. size[u]=1,mx[u]=0;
  27. for(int i=hd[u];i;i=nex[i])
  28. if(to[i]!=ff&&!vis[to[i]])
  29. getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]);
  30. mx[u]=max(mx[u],sn-size[u]);
  31. if(mx[u]<mx[root]) root=u;
  32. }
  33. void getdis(int u,int ff,int dep)
  34. {
  35. F[tmp].push_back(dep);
  36. for(int i=hd[u];i;i=nex[i])
  37. if(to[i]!=ff&&!vis[to[i]])
  38. getdis(to[i],u,dep+val[i]);
  39. }
  40. void prepare(int u)
  41. {
  42. vis[u]=1,G[u].push_back(++tmp),getdis(u,0,0);
  43. for(int i=hd[u];i;i=nex[i])
  44. if(!vis[to[i]])
  45. {
  46. G[u].push_back(++tmp),getdis(to[i],u,val[i]);
  47. root=0,sn=size[to[i]],getroot(to[i],u),go[u].push_back(root),prepare(root);
  48. }
  49. }
  50. ll calc(int u,int t)
  51. {
  52. int l=0,r=F[u].size()-1,pre=0;
  53. if(r<=0) return 0;
  54. ll sum=((ll)(r+1)*r)/2;
  55. while(l<r)
  56. {
  57. if(F[u][l]+F[u][r]<t)
  58. {
  59. sum-=(ll)(r-l);
  60. --r;
  61. }
  62. else
  63. {
  64. ++l;
  65. }
  66. }
  67. // printf("%lld\n",sum);
  68. return sum;
  69. }
  70. void dfs(int u,int t)
  71. {
  72. int i;
  73. if(!G[u].empty()) answer+=calc(G[u][0],t);
  74. for(i=1;i<(int)G[u].size();++i) answer-=calc(G[u][i],t);
  75. for(i=0;i<(int)go[u].size();++i) dfs(go[u][i],t);
  76. }
  77. ll check(int t)
  78. {
  79. answer=0,dfs(tt,t);
  80. return answer;
  81. }
  82. multiset<int>S;
  83. multiset<int>::iterator it;
  84. // 长度大于 len 即可
  85. void solve(int u)
  86. {
  87. int i,j;
  88. if(!G[u].empty())
  89. {
  90. for(j=0;j<F[G[u][0]].size();++j)
  91. {
  92. if(F[G[u][0]][j]>len) q.push(F[G[u][0]][j]);
  93. }
  94. if(G[u].size()>=2)
  95. {
  96. int t=G[u][1];
  97. for(j=0;j<F[t].size();++j) S.insert(-F[t][j]);
  98. }
  99. }
  100. for(i=2;i<G[u].size();++i)
  101. {
  102. int t=G[u][i];
  103. // F[t] 与 S 结合
  104. it=S.begin();
  105. for(j=0;j<F[t].size()&&(-(*S.begin())+F[t][0])>len;++j)
  106. {
  107. for(it=S.begin();it!=S.end();it++)
  108. {
  109. if(-(*it)+F[t][j]>len)
  110. {
  111. q.push(-(*it)+F[t][j]);
  112. }
  113. else break;
  114. }
  115. }
  116. for(j=0;j<F[t].size();++j)
  117. S.insert(-F[t][j]);
  118. }
  119. S.clear();
  120. for(int i=0;i<go[u].size();++i) solve(go[u][i]);
  121. }
  122. int main()
  123. {
  124. int i,j,tot=0;
  125. // setIO("input");
  126. scanf("%d%d",&n,&m);
  127. for(i=1;i<n;++i)
  128. {
  129. int a,b,c;
  130. scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c),tot+=c;
  131. }
  132. mx[root=0]=sn=n,getroot(1,0),tt=root,prepare(root);
  133. for(i=1;i<=tmp;++i) sort(F[i].begin(),F[i].end(),cmp);
  134. int l=0,r=tot,mid,ans=0;
  135.  
  136. while(l<=r)
  137. {
  138. mid=(l+r)>>1;
  139. if(check(mid)>=1ll*m) ans=mid,l=mid+1;
  140. else r=mid-1;
  141. }
  142. len=ans,solve(tt);
  143. while(q.size()<m) q.push(len);
  144. while(!q.empty()) printf("%d\n",q.top()), q.pop();
  145. return 0;
  146. }

  

BZOJ 3784: 树上的路径 点分治+二分+set的更多相关文章

  1. BZOJ.3784.树上的路径(点分治 贪心 堆)

    BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...

  2. bzoj 3784: 树上的路径 堆维护第k大

    3784: 树上的路径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 88  Solved: 27[Submit][Status][Discuss] ...

  3. bzoj 3784: 树上的路径【点分治+st表+堆】

    参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...

  4. BZOJ 3784: 树上的路径

    Description 问一棵树上前 \(k\) 大路径的边权. Sol 边分治. 非常感谢数据没有菊花图. 为了写写边分治试试然后就开了这道题. 边分治非常好想,选一条重边,分成两部分,然后分别求最 ...

  5. 【BZOJ-3784】树上的路径 点分治 + ST + 堆

    3784: 树上的路径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 462  Solved: 153[Submit][Status][Discuss ...

  6. 【BZOJ3784】树上的路径 点分治序+ST表

    [BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...

  7. BZOJ 1316: 树上的询问( 点分治 + 平衡树 )

    直接点分治, 用平衡树(set就行了...)维护. -------------------------------------------------------------------------- ...

  8. BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]

    传送门 题意: 路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段 第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学 昨天两 ...

  9. BZOJ 3697: 采药人的路径 点分治

    好久不做点分治的题了,正好在联赛之前抓紧复习一下. 先把边权为 $0$ 的置为 $-1$.定义几个状态:$f[dis][0/1],g[dis][0/1]$ 其中 $f$ 代表在当前遍历的子树内的答案. ...

随机推荐

  1. 【有奖征集】报表模板库邀您提反馈,轻松赢取P30!

    >>立即参赛 赛事初衷 大数据时代,数据的价值愈发彰显,什么样的报表才能真正帮助业务决策?这几乎是所有信息化建设的企业和个人都在思考的问题. 作为报表领域标杆企业,葡萄城于2017年推出了 ...

  2. Shell脚本编程(一)

    shell 脚本编程(一) 1 . shell 的作用 Shell的作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行一条,这种方式称为交互式(Interactive),Shell还有一 ...

  3. C++学习 之 继承(笔记)

    1.继承基础: 继承就像是生物里的遗传与变异,即派生类(子代)从基类(父代)那里继承基类的某些特性(遗传),并在此基础上拥有自己的特性(变异). C++派生语法: class Base//定义一个基类 ...

  4. sed---流文本操作

    一:sed基本命令 sed的使用格式 sed [optiona] 'command' files sed 参数[-nefir] 动作[n1,[n2]] function sed -n:只有经过sed特 ...

  5. MySQL性能优化(二):优化数据库的设计

    原文:MySQL性能优化(二):优化数据库的设计 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.n ...

  6. MySQL 主从同步架构中你不知道的“坑”(2)

    指定同步库情况 1.binlog_format= ROW模式‍ mysql> use testdb; Database changed mysql> show tables; +----- ...

  7. 15 Scrapy框架之CrawlSpider

    一.简介 CrawlSpider其实是Spider的一个子类,除了继承到Spider的特性和功能外,还派生除了其自己独有的更加强大的特性和功能.其中最显著的功能就是”LinkExtractors链接提 ...

  8. html/css弹性布局的几大常用属性详解

    弹性布局的名称概念: 1.容器:需要添加弹性布局的父元素:项目:弹性布局容器中的每一个子元素,称为项目. 2.主轴:在弹性布局中,我们会通过属性规定水平/垂直方向(flex-direction)为主轴 ...

  9. window.prompt()和 window.confirm()选择

    代码截图: 效果:  代码截图: 效果:

  10. 94. Binary Tree Inorder Traversal (Java)

    Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] ...