题解 [NOIP2015]运输计划

题面

解析

首先肯定是要求出每条路径的长度.

这个用节点到根的前缀和就行了(一开始脑抽写了个线段树...)

然后有一个显然的类似贪心的想法,

就是你改造的边肯定在最长的路径上,

(不然没有*用)

那么考虑枚举最长的路径上的边,计算改造它的答案,

对于边\(x\),路径可以分为两类:经过它的和不经过它的.

在它被改造后,经过它的路径就都减少了它的长度,

于是最长的就还是这条最长的路径,

而没经过它的就没有受到影响,取最长的路径,

因此删掉\(x\)的答案就是上面两种情况的\(max\),

但关键就是怎么求第二种情况:没经过\(x\)的最长的路径.

枚举边再一个个求似乎不可行,

我们可以考虑枚举路径计算它对边的贡献,

显然没在这条路径上的边都可以被这条路径更新,

于是考虑树剖,

这样一条路径就被划分成了若干个区间,

而区间的补集就是它要更新的边,

把边的答案对应到深度较大的点上,用线段树维护最大值即可.

code(代码挺长但仔细康康应该能懂):

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define fot for
  6. #define ls(a) a<<1
  7. #define rs(a) a<<1|1
  8. #define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
  9. using namespace std;
  10. inline int read(){
  11. int sum=0,f=1;char ch=getchar();
  12. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  13. while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
  14. return f*sum;
  15. }
  16. const int N=3000005;
  17. struct ques{int s,t,w;}q[N];
  18. struct edge{int to,next,w;}e[N<<1];
  19. struct tree{int l,r,sum,maxn,tag;}t[N<<1];
  20. struct qujian{int l,r;}sta[N];
  21. struct node{int size,son,id,fa,dep,top,val;}a[N];
  22. int n,m,tot,pla[N],ans;
  23. int head[N],cnt,s[N];
  24. inline void add(int x,int y,int w){
  25. e[++cnt]=(edge){head[x],y,w};head[x]=cnt;
  26. }
  27. inline void dfs1(int x,int fa){
  28. a[x].size=1;a[x].fa=fa;
  29. a[x].dep=a[fa].dep+1;
  30. for(int i=head[x];i;i=e[i].to){
  31. int k=e[i].next;
  32. if(k==fa) continue;
  33. s[k]=s[x]+e[i].w;
  34. dfs1(k,x);a[k].val=e[i].w;
  35. a[x].size+=a[k].size;
  36. if(a[k].size>a[a[x].son].size) a[x].son=k;
  37. }
  38. }
  39. inline void dfs2(int x,int top){
  40. a[x].top=top;a[x].id=++tot;
  41. pla[tot]=x;
  42. if(a[x].son) dfs2(a[x].son,top);
  43. for(int i=head[x];i;i=e[i].to){
  44. int k=e[i].next;
  45. if(k==a[x].fa||k==a[x].son) continue;
  46. dfs2(k,k);
  47. }
  48. }
  49. inline void build(int p,int l,int r){
  50. t[p].l=l;t[p].r=r;
  51. if(l==r) {t[p].sum=a[pla[l]].val;return ;}
  52. int mid=(l+r)>>1;
  53. build(ls(p),l,mid);build(rs(p),mid+1,r);
  54. }
  55. inline int lca(int x,int y){
  56. while(a[x].top!=a[y].top){
  57. if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
  58. x=a[a[x].top].fa;
  59. }
  60. if(a[x].dep>a[y].dep) swap(x,y);
  61. return x;
  62. }
  63. inline int dis(int x,int y){
  64. return s[x]+s[y]-2*s[lca(x,y)];
  65. }
  66. inline bool cmp(ques a,ques b){return a.w>b.w;}
  67. inline void Pushup(int p){
  68. t[p].maxn=max(t[ls(p)].maxn,t[rs(p)].maxn);
  69. }
  70. inline void Pushdown(int p){
  71. int ret=t[p].tag;
  72. t[ls(p)].tag=max(t[ls(p)].tag,ret);
  73. t[rs(p)].tag=max(t[rs(p)].tag,ret);
  74. t[ls(p)].maxn=max(t[ls(p)].maxn,ret);
  75. t[rs(p)].maxn=max(t[rs(p)].maxn,ret);
  76. }
  77. inline void change(int p,int l,int r,int w){
  78. if(l>r||!l||!r) return ;
  79. if(t[p].l>=l&&t[p].r<=r){
  80. t[p].maxn=max(t[p].maxn,w);
  81. t[p].tag=max(t[p].tag,w);
  82. return ;
  83. }
  84. Pushdown(p);
  85. int mid=(t[p].l+t[p].r)>>1;
  86. if(l<=mid) change(ls(p),l,r,w);
  87. if(r>mid) change(rs(p),l,r,w);
  88. Pushup(p);
  89. }
  90. inline bool cmp1(qujian a,qujian b){return a.l<b.l;}
  91. inline void find(int x,int y,int w){
  92. int top=0;
  93. while(a[x].top!=a[y].top){
  94. if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
  95. sta[++top]=(qujian){a[a[x].top].id,a[x].id};
  96. x=a[a[x].top].fa;
  97. }
  98. if(a[x].dep>a[y].dep) swap(x,y);
  99. sta[++top]=(qujian){a[x].id+1,a[y].id};
  100. int L=1,R;
  101. sort(sta+1,sta+top+1,cmp1);
  102. for(int i=1;i<=top;i++){
  103. R=sta[i].l-1;
  104. change(1,L,R,w);
  105. L=sta[i].r+1;
  106. }
  107. change(1,L,n,w);
  108. }
  109. inline int search(int p,int x){
  110. if(t[p].l==t[p].r) return t[p].maxn;
  111. Pushdown(p);
  112. int mid=(t[p].l+t[p].r)>>1;
  113. if(x<=mid) return search(ls(p),x);
  114. else return search(rs(p),x);
  115. }
  116. inline void solve(int x,int y){
  117. int pp=lca(x,y);
  118. while(x!=pp){
  119. ans=min(ans,max(q[1].w-a[x].val,search(1,a[x].id)));
  120. x=a[x].fa;
  121. }
  122. while(y!=pp){
  123. ans=min(ans,max(q[1].w-a[y].val,search(1,a[y].id)));
  124. y=a[y].fa;
  125. }
  126. }
  127. signed main(){
  128. n=read();m=read();
  129. for(int i=1;i<n;i++){
  130. int x=read(),y=read(),w=read();
  131. add(x,y,w);add(y,x,w);
  132. }
  133. for(int i=1;i<=m;i++){
  134. q[i].s=read(),q[i].t=read();
  135. }
  136. dfs1(1,0);dfs2(1,1);
  137. build(1,1,n);
  138. for(int i=1;i<=m;i++){
  139. q[i].w=dis(q[i].s,q[i].t);
  140. }
  141. for(int i=1;i<=m;i++) find(q[i].s,q[i].t,q[i].w);
  142. sort(q+1,q+m+1,cmp);
  143. ans=q[1].w;
  144. fot(int i=1;i<=m;i++)
  145. if(q[i].w==q[1].w) solve(q[i].s,q[i].t);
  146. else break;
  147. printf("%d\n",ans);
  148. return 0;
  149. }

题解 [NOIP2015]运输计划的更多相关文章

  1. NOIP2015 运输计划(bzoj4326)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 886  Solved: 574[Submit][Status] ...

  2. [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划

    [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...

  3. [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

    [NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...

  4. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  5. NOIP2015 运输计划(二分+LCA+差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status] ...

  6. 数据结构(树链剖分):COGS 2109. [NOIP2015] 运输计划

    2109. [NOIP2015] 运输计划 ★★★   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:1 s   内存限制:256 MB [题目描 ...

  7. BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1930  Solved: 1231[Submit][Statu ...

  8. cogs2109 [NOIP2015] 运输计划

    cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...

  9. LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*

    LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...

随机推荐

  1. 【转载】spring mvc 后端获得前端传递过来的参数的方法

    1.通过HttpServletRequest 获得 HttpServletRequest.getParameter(参数名),可以获得form表单中传递的参数,或ajax或url中传递过来的参数,如果 ...

  2. 向前引用 ? float VS long ? 这些知识你懂吗?

    thinking in java 读书笔记(感悟): 作者:淮左白衣 : 写于 2018年4月2日18:14:15 目录 基本数据类型 float 和 long 谁更大 System.out.prin ...

  3. C# LoadXml System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

    去掉BOM头 writer = new XmlTextWriter(stream, new UnicodeEncoding(false,false)); 如果是UTF8 writer = new Xm ...

  4. CAS 5.x搭建常见问题系列(3).Failure to find org.apereo.cas:cas-server-support-pm-jdbc:jar:5.1.9

    错误内容 cas overlay的pom.xml增加了cas-server-support-pm-jdbc.jary依赖后, 打包(mvn package)出现如下的报错 D:\casoverlay\ ...

  5. (九)二进制文件在webservice中的处理(以DataHandler方式)

    一.需求 1. 客户端从服务端下载附件 2. 客户端上传附件到服务端 二.案例 本章通过DataHander的方式来进行传递. 注意:   1:接口中要定义@MTOM 2:方法中要使用@XmlMime ...

  6. 关于hashcode 和 equals 的内容总结

    第一:equals() 的作用是 表示其他对象是否“等于”这个对象. 在Object源码里面    equals的作用等价于 ==   即 用来比较俩个对象的内存地址是否相同 public boole ...

  7. 听课笔记--DP--Authentication Failed

    Authentication Failed https://www.codechef.com/problems/AUTHEN/ 从一个长为N+K的由小写字母组成的字符串中删去K个字符, 可以得到多少种 ...

  8. Apache ---- Solrl漏洞复现

    Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引:也可以通过Http Get操 ...

  9. JS 知识图

  10. iOS-OC中常见的一些宏

    /* 1. 颜色 */ #define PCBRGBColorA(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b ...