运输计划[NOIP-Day2-T3](二分,树上差分)

题目

Luogu
给你一个 n n n 个点的树,每条边 ( u i , v i ) (u_i,v_i) (ui,vi) 通过时间为 t i t_i ti ,现在有 m m m 个订单同时运送,第 i i i 个订单从 s i s_i si 出发到 t i t_i ti m m m 个订单同时出发,你现在可以让一条边通过时间为 0 0 0 ,求最大运输时间最小值?
1 ≤ n , m ≤ 3 ⋅ 1 0 5 1\le n,m\le 3\cdot 10^5 1n,m3105

思路

这跟天天爱跑步很像,都是同时出发…
我们可以预处理出 s i s_i si t i t_i ti 的长度 l e n i len_i leni
最大值最小,考虑二分最大值 x x x
那么对于 l e n i ≥ x len_i\ge x lenix 的所有路径都需要被减少,假设有 c n t cnt cnt
但是你发现你只有一次修改的权利
于是考虑边差,就是找出覆盖次数等于 c n t cnt cnt 的最大的边权 M a x 2 Max_2 Max2
再找出 c n t cnt cnt 条中长度最大的
只需要满足 M a x 1 − M a x 2 < = x Max_1-Max_2<=x Max1Max2<=x 即可


这道题似乎倍增被卡了…,以后还是写树剖吧…

代码

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<cstdio>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define MAXN 300000
#define mp make_pair
#define INF 0x3f3f3f3f
struct Edge{
	int v,w,id,nxt;
}edge[2*MAXN+5];
int ecnt,head[MAXN+5];
void Addedge(int u,int v,int w,int id){
	edge[++ecnt]=(Edge){v,w,id,head[u]},head[u]=ecnt;
	edge[++ecnt]=(Edge){u,w,id,head[v]},head[v]=ecnt;
	return ;
}
int n,m,siz[MAXN+5],dep[MAXN+5],fa[MAXN+5];
int len[MAXN+5],fd[MAXN+5],Maxson[MAXN+5],Tp[MAXN+5];
void DFS1(int u){
	siz[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v,w=edge[i].w,id=edge[i].id;
		if(v==fa[u]) continue;
		len[v]=len[u]+w;
		fa[v]=u,fd[v]=id,dep[v]=dep[u]+1;
		DFS1(v);
		siz[u]+=siz[v];
		if(siz[v]>siz[Maxson[u]])
			Maxson[u]=v;
	}
	return ;
}
void DFS3(int u,int tp){
	Tp[u]=tp;
	if(!Maxson[u])
		return ;
	DFS3(Maxson[u],tp);
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v==fa[u]||v==Maxson[u]) continue;
		DFS3(v,v);
	}
	return ;
}
int LCA(int u,int v){
	while(Tp[u]!=Tp[v]){
		if(dep[Tp[u]]<=dep[Tp[v]])
			v=fa[Tp[v]];
		else u=fa[Tp[u]];
	}
	return dep[u]<dep[v]?u:v;
}
int U[MAXN+5],V[MAXN+5],W[MAXN+5],cha[MAXN+5];
int s[MAXN+5],t[MAXN+5],Lca[MAXN+5],Dis[MAXN+5];
inline int Max(register int a,register int b){return a>b?a:b;}
void DFS2(int u){
	for(register int i=head[u];i;i=edge[i].nxt){
		register int v=edge[i].v,id=edge[i].id;
		if(v==fa[u]) continue;
		DFS2(v),cha[fd[u]]+=cha[id];
	}
	return ;
}
bool check(int x){
	memset(cha,0,sizeof(cha));
	register int cnt=0,Max1=0,Max2=0;
	for(register int i=1;i<=m;i++)
		if(Dis[i]>x){
			cnt++;
			Max1=max(Max1,Dis[i]);
			cha[fd[s[i]]]++,cha[fd[t[i]]]++;
			cha[fd[Lca[i]]]-=2;
		}
	if(Max1<=x)
		return 1;
	DFS2(1),cha[0]=0;
	for(register int i=1;i<=n;i++)
		if(cha[i]==cnt)
			Max2=Max(Max2,W[i]);
	return Max1-Max2<=x;
}
int main(){
	n=read(),m=read();
	for(register int i=1;i<n;i++){
		U[i]=read(),V[i]=read(),W[i]=read();
		Addedge(U[i],V[i],W[i],i);
	}
	DFS1(1);
	DFS3(1,1);
	for(register int i=1;i<=m;i++){
		s[i]=read(),t[i]=read();
		Lca[i]=LCA(s[i],t[i]);
		Dis[i]=len[s[i]]+len[t[i]]-2*len[Lca[i]];
	}
	register int L=-1,R=300000000;
	while(L+1<R){
		register int Mid=(L+R)>>1;
		if(check(Mid)) R=Mid;
		else L=Mid;
	}
	printf("%d\n",R);
	return 0;
}

思考

C S P CSP CSP 遇到最大值最小这种问题先考虑二分答案

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值