P4616 [COCI2017-2018#5] Pictionary
时间:2021-09-07
本文章向大家介绍 P4616 [COCI2017-2018#5] Pictionary,主要包括 P4616 [COCI2017-2018#5] Pictionary使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
$ \texttt{Introduction} $
原题+思维
$ \texttt{Solution} $
本题题意可以简化为 $ i $ 和 $ j $ 之间连一条 $ m-\gcd(i,j)+1 $ 的边,然后问你从 $ a $ 走到 $ b $ 的道路中的最大值的最小值是多少。
简化之后的问题,难度就在于建边了,首先肯定不能建出一张单纯的图,我们发现答案要尽量的小,所以我们按价值从小到大加边,如果两个点已经相连,那么便不用再连,最后我们会得出一棵树。
但大体的思路怎么具体实现呢?
首先有一个很 $ naive $ 的想法,我们从大到小枚举最大公约数,然后找到最大公约数为这个数的两个点,按照上述的方法连边,但是这样时间复杂度会爆炸,亲测只有 $ 32pts $,那怎么办呢?
我们可以发现,选取的两个数一定都是最大公约数的倍数,那么我们直接将最大公约数和他的倍数连边,这样就把最大公约数是这个数的情况的边都连好了,也许你要问那如果会连多余的边呢,其实不会因为我们是要判断过得,如果最大公约数比这个数要大,那么前面一定已经连过边,就不会再连了。
建好这棵树之后就是经典操作了,我们要找两点之间的边的最大值,可以用倍增实现,具体可以参考[NOIP2013 提高组] 货车运输,然后这道题就做好了。
int find(int x)
{
if (ff[x]==x) return ff[x];
ff[x]=find(ff[x]);return ff[x];
}
void add(int x,int y,int z)
{
cnt++;a[cnt]=y;b[cnt]=d[x];c[cnt]=z;d[x]=cnt;
}
void sc(int x,int y) //找两点之间最大边
{
int t,i;
if (e[x]>e[y]){
t=x;x=y;y=t;
}
for (i=lg[n];i>=0;i--)
if (e[f[y][i]]>=e[x])
{
ans=max(ans,u[y][i]);
y=f[y][i];
}
if (x==y) return ;
for (i=lg[n];i>=0;i--)
if (f[x][i]!=f[y][i])
{
ans=max(ans,max(u[x][i],u[y][i]));
x=f[x][i];y=f[y][i];
}
ans=max(ans,max(u[x][0],u[y][0]));
}
int main()
{
//ios::sync_with_stdio(0);cin.tie();cout.tie();
n=read();m=read();T=read();
for (i=1;i<=n;i++) ff[i]=i;
for (i=m;i>=1;i--)
{
for (j=2;j<=n/i;j++)
{
x=i;y=i*j;
r1=find(x);r2=find(y);
if (r1!=r2)
{
add(x,y,m-i+1);add(y,x,m-i+1);
tot++;
}
ff[r1]=r2;
if (tot==n-1) break;
}
if (tot==n-1) break;
}//建图
for (i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
t=1;w=1;f2[1]=1;e[1]=1;
while (t<=w)
{
for (i=d[f2[t]];i;i=b[i])
{
if (e[a[i]]==0)
{
e[a[i]]=e[f2[t]]+1;
f[a[i]][0]=f2[t];u[a[i]][0]=c[i];
for (j=1;j<=lg[n];j++)
{
f[a[i]][j]=f[f[a[i]][j-1]][j-1];
u[a[i]][j]=max(u[a[i]][j-1],u[f[a[i]][j-1]][j-1]);
}
w++;f2[w]=a[i];
}
}
t++;
}//倍增的预处理
for (;T;T--)
{
x=read();y=read();ans=0;
sc(x,y);
printf("%d\n",ans);
}
return 0;
}
原文地址:https://www.cnblogs.com/huangxuze/p/15237752.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 在 Kubernetes 上使用 Argo 实现 CI/CD
- 微信小程序:授权登录 + 基于token的身份验证详解
- 「最强」Lettuce 已支持 Redis6 客户端缓存
- Go中校验一个字符串是否是有效的JSON字符串
- 在 Vue 中,如何从插槽中发出数据
- Azure DevOps+Docker+Asp.NET Core 实现CI/CD(二.创建CI持续集成管道)
- 这样的奇技淫巧,劝你不用也罢
- 我服务又双叒叕奔溃了,含泪干货分享
- Azure DevOps+Docker+Asp.NET Core 实现CI/CD(一 .简介与创建自己的代理池)
- Android数据库高手秘籍(十二),LitePal的索引功能
- 使用pm2管理go应用进程
- 用Docker搭建Redis主从复制的集群
- IDEA 非常重要的一些设置项 → 一连串的问题差点让我重新用回 Eclipse !
- ArrayList源码分析(基于jdk1.8)(二):subList陷阱补充
- Windows10中安装Docker