P8626 [蓝桥杯 2015 省 A] 灾后重建 解题报告

一个结论,如果要让路径上的最大值最小,路径必然在原图的最小生成树上。

因为如果不在,那么经过的非树边的权值必然会小于会与它组成环的树边的最大值,此时就可以替换。

看到题目中的 \(k\),可以根号分治。

\(k>\sqrt n\) 的时候,需要计算的点的数量就 \(<\sqrt n\),不超过 250 个,就可以暴力枚举每个点。

因为是 \(max\),可以重复计算,根据 LCA 的性质,每一次只需要在上一个点求解完后的最近公共祖先的基础上叠加计算。

时间复杂度 \(O(q\sqrt n logn)\)

对于剩下的部分,因为 \(k\) 很小,情况很少,所以可以预处理出每一个 \(i\)\(i+k\) 的贡献。

此时,对于每个余数,建线段树,然后 \(O(logn)\) 求解即可。

但是这样的空间复杂度很大,考虑优化。

注意到题目中没有限制强制在线,可以离线处理,将所有询问按 \(k\) 为第一关键字,\(c\) 为第二关键字排序。

此时,可以在 \(k\) 改变时更新 \(n\) 个数的贡献,\(c\)\(k\) 改变时,重新建线段树。

此时,更新和查询的时间复杂度均为 \(O(n\sqrt n logn)\)

代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#define lid id<<1
#define rid id<<1|1
using namespace std;
int n,m,q,head[50005],edgenum;
struct node{int u,v,w;
}a[200005];
struct edge{int to,nxt,val;
}e[100005];
struct ques{int l,r,k,c,id;
}qs[50005];
void add_edge(int u,int v,int w)
{e[++edgenum].nxt=head[u];e[edgenum].to=v;e[edgenum].val=w;head[u]=edgenum;
}
bool cmp(node x,node y)
{return x.w<y.w;
}
int f[50005];
int find(int x)
{if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
int f1[50005][18],dep[50005],d[50005][18];
int dfn[50005],tot,ans[50005];
void dfs(int u,int fa)
{dep[u]=dep[fa]+1,f1[u][0]=fa;dfn[u]=++tot;for(int i=1;i<=16;i++){f1[u][i]=f1[f1[u][i-1]][i-1];d[u][i]=max(d[u][i-1],d[f1[u][i-1]][i-1]);}for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(v==fa) continue;d[v][0]=e[i].val;dfs(v,u);}
}
bool cmp1(ques x,ques y)
{if(x.k==y.k) return x.c<y.c;return x.k<y.k;
}
int lca,mx;
void getlca(int x,int y)
{if(dep[x]<dep[y]) swap(x,y);mx=0;for(int i=16;i>=0;i--){if(dep[f1[x][i]]>=dep[y]){mx=max(mx,d[x][i]);x=f1[x][i];}if(x==y){lca=x;return;}}for(int i=16;i>=0;i--){if(f1[x][i]!=f1[y][i]){mx=max(mx,max(d[x][i],d[y][i]));x=f1[x][i],y=f1[y][i];}}lca=f1[x][0],mx=max(mx,max(d[x][0],d[y][0]));
}
int get(int l,int r,int k,int c)
{int st=l/k;st=st*k+c;if(st<l) st+=k;int lc=st,res=0;for(int i=st+k;i<=r;i+=k){getlca(lc,i);res=max(res,mx);lc=lca;}return res;
}
int p[50005],b[50005],cnt;
void getarr(int x)
{for(int i=1;i<=n;i++) p[i]=0;for(int i=1;i<=n-x;i++){getlca(i,i+x);p[i]=mx;}
}
struct seg_tr{int l,r,val;
}tr[200005];
void build(int id,int l,int r)
{tr[id].l=l,tr[id].r=r;if(l==r){tr[id].val=b[l];return;}int mid=(l+r)>>1;build(lid,l,mid);build(rid,mid+1,r);tr[id].val=max(tr[lid].val,tr[rid].val);
}
int query(int id,int l,int r)
{if(tr[id].l==l&&tr[id].r==r){return tr[id].val;}int mid=(tr[id].l+tr[id].r)>>1;if(r<=mid) return query(lid,l,r);else if(l>mid) return query(rid,l,r);else return max(query(lid,l,mid),query(rid,mid+1,r));
}
void new_tr(int x,int y)
{if(y==0) y=x;cnt=0;for(int i=y;i<=n-x;i+=x){b[++cnt]=p[i];}build(1,1,cnt);
}
int getans(int l,int r,int k,int c)
{int st=l/k,ed=r/k;if(c==0){st=(l+k-1)/k;return query(1,st,ed-1);}if(st*k+c<l) st++;if(ed*k+c>r) ed--;
//	printf("%d %d %d\n",st,ed,cnt);return query(1,st+1,ed);
}
int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);a[i]=(node){u,v,w};}for(int i=1;i<=q;i++){int l,r,k,c;scanf("%d%d%d%d",&l,&r,&k,&c);qs[i]=(ques){l,r,k,c,i};}sort(a+1,a+m+1,cmp);for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m;i++){int u=a[i].u,v=a[i].v;if(find(u)==find(v)) continue;f[find(u)]=find(v);add_edge(u,v,a[i].w);add_edge(v,u,a[i].w);}dfs(1,0);sort(qs+1,qs+q+1,cmp1);int len=sqrt(n);
//	printf("1");for(int i=1;i<=q;i++){if(qs[i].k>len){
//		printf("%d",i);ans[qs[i].id]=get(qs[i].l,qs[i].r,qs[i].k,qs[i].c);continue;}if(qs[i].k!=qs[i-1].k){getarr(qs[i].k);
//			for(int j=1;j<=n;j++)
//			{
//				printf("%d ",p[j]);
//			}
//			printf("\n");new_tr(qs[i].k,qs[i].c);}else if(qs[i].c!=qs[i-1].c){new_tr(qs[i].k,qs[i].c);}
//		printf("%d ",qs[i].id);ans[qs[i].id]=getans(qs[i].l,qs[i].r,qs[i].k,qs[i].c);}
//	printf("1");for(int i=1;i<=q;i++){printf("%d\n",ans[i]);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/878757.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【vscode配置】一种基于Beta版UTF-8解决VSCode中C/C++/Python等的中文乱码问题的简便方法

在VSCode或其他编码场景下输入输出中文时会出现乱码,常用的解决方式是通过GBK编码重新打开或保存文件后再使用 但又是来回切换保存会导致代码中的中文变成乱码难以恢复 而且个人觉得来回切换很麻烦 下面给出一种了解到的解决方法:控制面板——时钟和区域——区域——管理——…

Graphviz-画数据结构图的利器

1.Win系统上的安装 安装Graphviz的方法有很多,以下是手动安装的方式: 1.访问 https://graphviz.org/download/,选择你想要下载的版本,手动安装选择ZIP安装包;2.解压下载的zip压缩包到你选择的文件目录,例如:D:\Graphviz-12.2.1-win64; 3.将Graphviz的安装目录(如:D:\…

4G优先级切换

本文来自博客园,作者:{IceSparks},转载请注明原文链接:https://www.cnblogs.com/IceSparks/p/18698508

4G与5GSIB对比

本文来自博客园,作者:{IceSparks},转载请注明原文链接:https://www.cnblogs.com/IceSparks/p/18698503

AI赋能软件测试:未来已来,你准备好了吗?

ps:文末有福利领取哦引言 在数字化转型的浪潮中,软件测试作为保障产品质量的关键环节,正面临着前所未有的挑战。 传统的测试方法已难以满足快速迭代和复杂场景的需求,而人工智能(AI)的引入,则为软件测试带来了革命性的变化。 本文将从现状、优势、挑战及未来趋势四个方面…

C语言 输出回文数

回文数,既把数值的每个数 颠倒输出(从右往左输出),再合起来的数如果和原来的值相等 例:输出0 至 1993 的回文数#include <stdio.h>int main() { int i ,x ,d ,a ; for(i=0;i<=1993;i++) {a = i; x = 0; while (a != 0) { d = a%10; //每次都取a值的最后一位 x = …

洛谷 P3842 [TJOI2007] 线段 题解

题目大意 原题链接 给你一个大小为 \(n \times n\) 的矩阵,上面有 \(n\) 条线段(一行一条)。你只能向右,向下,向左走。每一条线段都必须完整的经过。请问从 \((1,1)\) 到 \((n,n)\) 最短路径长度是多少? 解法 这道题可以使用最短路或者DP来做。我觉得DP本题更简单一点所以我…

数据降维技术研究:Karhunen-Love展开与快速傅里叶变换的理论基础及应用

在现代科学计算和数据分析领域,数据降维与压缩技术对于处理高维数据具有重要意义。本文主要探讨两种基础而重要的数学工具:Karhunen-Love展开(KLE)和快速傅里叶变换(FFT)。通过分析这两种方法的理论基础和应用特点,阐述它们在数据降维中的优势和适用场景。 Karhunen-Lov…

一个Python GC的小Bug

这个代码是在看了“码农高天”的视频照模仿的。虽然 GC 能完成大部分内存管理的工作,但是基于性能计数器的GC确实存在小 Bug,这一点还是需要通过del和gc.collect手动管理。 from typing import Optionalclass Object:def __init__(self, name: str) -> None:self.obj: Opt…

2月做题记录

还有一个月。2月做题记录✩ trick ✯ 会大部分,要\(tj\)提示 ✬ 会小部分/完全没想到,看了\(tj\)才会 ◈ 脑电波 ✡ 有某一算法的神秘通用性质 ⊗ 待补目录2月做题记录字符串CF1827CCF1913FP10716P11150 ✩✯树[NOI2021] 轻重边做法1 ✩做法2做法3 ✡《简单树剖练习题》[QOJ9…

第六节 特征提取和无监督学习

没有标签y依旧提取出特征你的模型朝着哪个方向压缩特征,由你的标签来定自监督学习:从x中提取一部分作为自己的标签y,然后用x预测y 在自监督学习中,需要根据数据的特点设计一些自监督任务,这些任务通常基于数据的一些内在属性或关系来构建。例如,在图像数据中,可以设计图像…