传送门

文章目录

  • 题目描述
  • 解析
  • 问题
  • 代码

题目描述

解析

求最大值的最小值
容易想到二分
然后。。。就没有然后了。。。
看了题解
学会了一个新技能:树上差分
(其实学长之前好像讲过。。。)

一般的,对于一条A到B的路径,如果要将其全部加上一个值w。我们可以把AB两点的前缀加w,再把它们的lca及lca的父亲减去w,最后统计时用dfs统计,每个点的价值就是其本身及子树的前缀值之和
画个图就能很直观的看出来,请读者自行动笔探究~~(绝对不是我懒)~~
lca可以用许多算法优化到log,这样时间复杂度就很优秀啦

本题对于一个二分出来的值mid,如果有一些路径的长度大于mid,那么删的边一定是这些不符合的路径的公共边(不然它还是不符合)
就相当与每次把不符合的路径上的点全部加1,再统计点权恰好等于不符合路径个数的点,它们之间的边,就是可以删的边(这就能用差分啦)
其中选一条最大的,看减完它行不行即可

问题

本题到这里思路就结束了
但真正做起来真的有点搬砖。。。
还遇到了很多细节问题

1.树上倍增的时候要注意单链时最后不用再跳一边father了!
2.300000的log大于15(我掰手指头当成30000了。。。调了好久)
3.双向边要开二倍!!!!

这都是经常遇到的问题,代码复杂起来就又忘了,一定要引以为戒,注意细节!

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e5+100;
int n,m;
struct node{int to,nxt,v;
}p[2*N];
int fi[N],cnt=-1;
void addline(int x,int y,int v){p[++cnt]=(node){y,fi[x],v};fi[x]=cnt;
}int dep[N],fa[N],fv[N];
void dfs(int x,int f){for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;fa[to]=x;dep[to]=dep[x]+1;fv[to]=p[i].v;dfs(to,x);}return;
}
int pl[22][N],dis[22][N],mi[22];
void solve(){mi[0]=1;for(int i=1;i<=20;i++) mi[i]=mi[i-1]*2;for(int i=2;i<=n;i++){pl[0][i]=fa[i];dis[0][i]=fv[i];}for(int k=1;k<=20;k++){for(int i=1;i<=n;i++){if(dep[i]<mi[k]) continue;pl[k][i]=pl[k-1][pl[k-1][i]];dis[k][i]=dis[k-1][i]+dis[k-1][pl[k-1][i]];}}return;
}
int place,tot;
void find(int x,int y){tot=0;if(dep[x]<dep[y]) swap(x,y);for(int k=20;k>=0;k--){if(dep[x]-mi[k]>=dep[y]){tot+=dis[k][x];x=pl[k][x];}}for(int k=20;k>=0;k--){if(dep[x]<mi[k]||pl[k][x]==pl[k][y]) continue;tot+=dis[k][x];x=pl[k][x];tot+=dis[k][y];y=pl[k][y];
//      printf("x=%d y=%d tot=%d\n",x,y,tot);}place=x;if(x!=y){tot+=fv[x];tot+=fv[y];place=fa[place];}
}struct node2{int x,y,len,lca;
}q[N];
int a,b,c;int num;
int pre[N],sum[N];
void dfs2(int x,int f,int &ans){sum[x]=pre[x];for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dfs2(to,x,ans);sum[x]+=sum[to];}if(sum[x]!=num) return;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(sum[to]==num){ans=max(ans,p[i].v);
//          printf("x=%d y=%d v=%d\n",x,to,fv[to]);}}return;
}
bool check(int mid){int mx=0;num=0;memset(pre,0,sizeof(pre));memset(sum,0,sizeof(sum));
//  printf("check: (%d)\n",mid);for(int i=1;i<=m;i++){if(q[i].len>mid){num++;mx=max(mx,q[i].len);pre[q[i].x]++;pre[q[i].y]++;pre[q[i].lca]--;pre[fa[q[i].lca]]--;}}if(num==0) return true;int ans=0;dfs2(1,0,ans);
//  printf("  num=%d ans=%d\n",num,ans);if(mx-ans<=mid) return true;else return false;
}
int main(){memset(fi,-1,sizeof(fi));
//  printf("%d",sizeof(pl)/1024/1024);scanf("%d%d",&n,&m);for(int i=1;i<n;i++){scanf("%d%d%d",&a,&b,&c);addline(a,b,c);addline(b,a,c);}dfs(1,0);solve();
//  for(int i=1;i<=n;i++) printf("i=%d fa=%d dep=%d\n",i,fa[i],dep[i]);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);find(a,b);q[i]=(node2){a,b,tot,place};
//      printf("tot=%d pl=%d\n",tot,place);}int st=0,ed=2e9;while(st<ed){//      printf("st=%d ed=%d\n",st,ed);int mid=(st+ed)>>1;if(check(mid)) ed=mid;else st=mid+1;}printf("%d",st);
}
/*
12 3
1 2 8
1 3 1
1 4 8
2 5 6
2 7 5
2 6 4
6 8 7
6 9 5
3 10 6
3 12 3
10 11 5
1 11
3 11
10 116 4
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
2 4
*/

洛谷P2680:运输计划(倍增、二分、树上差分)相关推荐

  1. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  2. [luogu2680] 运输计划 (lca+二分+树上差分)

    传送门 Description Input Output 一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间. Sample Input 6 3 1 2 3 1 6 4 3 1 7 4 3 ...

  3. 洛谷 2680 运输计划 题解

    博客观赏效果更佳 题意简述 n n n个点的边带权树,给 m m m条关键的链.把树上一条边的权值变为0,使得 m m m条链的和中,最大值最小. n , m < = 1 e 5 n,m< ...

  4. P2680 运输计划

    传送门 十分显然完成工作的时间和航耗时最长的运输计划有关 所以题目意思就是要求最大值最小 所以可以想到二分 把所有大于mid时间的航线打上标记,显然删边只能在所有这些航线的公共路径上 要如何快速打标记 ...

  5. 洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA

    洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA 二分交费最多的一次的钱数 然后只将符合要求的边加入图中 如果到终点的最短路大于等于血量 或者直接起点不能到达终点 那么说明不符合要求 需要 ...

  6. 洛谷 P1137 旅行计划 题解

    洛谷 P1137 旅行计划 题解 洛谷 P1137 题目 小明要去一个国家旅游.这个国家有 N N N个城市,编号为1至 N N N,并且有 M M M条道路连接着,小明准备从其中一个城市出发,并只往 ...

  7. 洛谷 P1137 旅行计划 1

    题目描述 小明要去一个国家旅游.这个国家有N个城市,编号为1-N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止. 所以他就需要选择最先到达的城市,并制定一条路线以城市i为终 ...

  8. P2680 运输计划(树上差分+lca+二分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  9. luogu P2680 运输计划 (二分答案+树上差分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

最新文章

  1. 7纳米duv和euv_要超车台积电 三星宣布采用EUV技术7纳米制程完成验证
  2. golang中的strings.ToTitle
  3. Nginx 源码分析:ngx_hash_t(上)
  4. JZOJ 5048. 【GDOI2017模拟一试4.11】IQ测试
  5. Python机器学习---2.聚类算法理论部分
  6. 嵌入式和非嵌入式_我如何向非技术同事解释词嵌入
  7. [SHOI2011]双倍回文 manacher
  8. ubuntu中mysql怎么退出命令_Ubuntu中mysql启动和关闭
  9. Node文件服务器(文件上传)
  10. bzoj 3208 花神的秒题计划I
  11. 网线连接电脑共享文件传递
  12. 成功自我暗示三大规律
  13. acr122 java,ACR122开发包 SDK v1.1 [CDR 146]
  14. html+css常用代码(前端必备)
  15. 编写一个函数,使其向主函数返回您输入的3个整数参数中的最大值,并在主函数中输出该值。
  16. ppt怎么设置页面比例为4:3
  17. 电脑浏览android,直接在电脑上浏览操作安卓手机
  18. Neutral Graph Collaborative Filtering——论文提炼
  19. Java 编程技巧之样板代码
  20. AI研习丨专题:面向防疫的5G巡检机器人技术与应用

热门文章

  1. 如何发送html email,如何发送HTML电子邮件?
  2. mysql双机互备linux成功的_配置MySQL双机热备 - Linux服务器MySQL双机热备份试验_数据库技术_Linux公社-Linux系统门户网站...
  3. 点歌软件测试自学,实际歌唱对比测试
  4. 没找到rpm命令_Mysql的命令总结和PyMysql
  5. mysql 5.7.6 5.7.19_MySQL数据库之Mysql 5.7.19 免安装版遇到的坑(收藏)
  6. php 输入值,php-HTML输入值更改
  7. 3dsmax子菜单无法选择_3DsMax—用平面图片制作3D模型
  8. c语言用递归法判断回文字符串,递归方式判断一个字符串是否为回文字符串
  9. python怎么安装bokeh_python怎么安装bokeh
  10. vue 离开页面事件_【必看】58 道 Vue 常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度...