[数论][LCA][并查集]JZOJ 5782 城市猎人

2024-01-18 05:30

本文主要是介绍[数论][LCA][并查集]JZOJ 5782 城市猎人,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description
有n个城市,标号为1到n,修建道路花费m天,第i天时,若gcd(a,b)=m-i+1,则标号为a的城市和标号为b的城市会建好一条直接相连的道路,有多次询问,每次询问某两座城市最早什么时候能连通。
 
Input
第一行输入三个正整数n,m,q,其中q表示询问个数。
接下来q行,每行两个正整数x,y,表示询问城市x和城市y最早什么时候连通。
 
Output
输出q行,每行一个正整数,表示最早连通的天数
 
Sample Input
Input 1
8 3 3
2 5
3 6
4 8
Input 2
25 6 1
20 9
Input 3
9999 2222 2
1025 2405
3154 8949
Sample Output
Output 1
3
1
2
Output 2
4
Output 3
1980
2160
Data Constraint
对于40%的数据,n≤ 1000,q<=100000
对于100%的数据,1 ≤ n,q≤ 100000,1<=m<=q

分析

显然对于gcd(a,b)=k,a与b都是k的倍数且a/k+1=b/k

那么我们就知道,第i天会有这样一个数列变得连通:m-i+1,2*(m-i+1),3*(m-i+1),...

那么问题就变成了求问两个连通块之间最早的连通时间

我们想到了并查集,但是不能路径压缩,这样会破坏数据详细性

只能按秩合并咯

然后对于每个点给一个ti表示i这个点与父亲相连通的最早时间

那么我们预处理好并查集,求x,y到它们LCA(不包括LCA,注意!)的max{ti 即可

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=1+1e5;
int n,m,q;
int f[N],r[N],t[N],d[N];int Get(int x) {if (x==f[x]) return x;int root=Get(f[x]);d[x]=d[f[x]]+1;return root;
}int Ask(int x,int y) {int ans=0;if (d[x]<d[y]) swap(x,y);while (d[x]>d[y]) ans=max(ans,t[x]),x=f[x];while (x!=y) {ans=max(ans,max(t[x],t[y]));x=f[x];y=f[y];}return ans;
}int main() {freopen("pictionary.in","r",stdin);freopen("pictionary.out","w",stdout);scanf("%d%d%d",&n,&m,&q);for (int i=1;i<=n;i++) f[i]=i,r[i]=1;for (int i=1;i<=m;i++) {for (int j=2;j<=n/(m-i+1);j++) {int u=Get((m-i+1)*(j-1)),v=Get((m-i+1)*j);if (u==v) continue;if (r[u]<=r[v]) {f[u]=v;t[u]=i;r[v]=max(r[u]+1,r[v]);}else {f[v]=u;t[v]=i;r[u]=max(r[v]+1,r[u]);}}}for (int i=1;i<=n;i++) Get(i);for (int i=0;i<q;i++) {int a,b;scanf("%d%d",&a,&b);Get(a);Get(b);printf("%d\n",Ask(a,b));}fclose(stdin);fclose(stdout);
}
View Code

 

转载于:https://www.cnblogs.com/mastervan/p/9445484.html

这篇关于[数论][LCA][并查集]JZOJ 5782 城市猎人的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/618155

相关文章

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

并查集基础与简单扩展应用

并查集 基础题目路径压缩 扩展应用扩展题目1扩展题目2 并查集的结构是一棵树 并查集有两种功能,一种是判断两个元素是否在同一集合,第二种是合并两个集合 并查集的实现需要记录每个节点的父亲节点 判断两个元素是否在同一集合,即判断两个元素的祖宗节点是否是一个节点(祖宗代表整棵树的根节点) 合并两个集合,即将任意一个集合祖宗的爸爸改为另一个集合的祖宗 基础题目 一共有