有n个城市,标号为1到n,修建道路花费m天,第i天时,若gcd(a,b)=m-i+1,则标号为a的城市和标号为b的城市会建好一条直接相连的道路,有多次询问,每次询问某两座城市最早什么时候能连通。
对于40%的数据,n≤ 1000,q<=100000
对于100%的数据,1 ≤ n,q≤ 100000,1<=m<=q
如果想到了kruskal重构树,那应该是学傻了 像我一样
直接并查集按秩合并就行了,边权就是合并时的时间,查询就暴力爬链,查询两点之间的最大边权
硬核优化
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 %:pragma GCC optimize(2) 2 %:pragma GCC optimize(3) 3 %:pragma GCC optimize("Ofast") 4 %:pragma GCC optimize("inline") 5 %:pragma GCC optimize("-fgcse") 6 %:pragma GCC optimize("-fgcse-lm") 7 %:pragma GCC optimize("-fipa-sra") 8 %:pragma GCC optimize("-ftree-pre") 9 %:pragma GCC optimize("-ftree-vrp") 10 %:pragma GCC optimize("-fpeephole2") 11 %:pragma GCC optimize("-ffast-math") 12 %:pragma GCC optimize("-fsched-spec") 13 %:pragma GCC optimize("unroll-loops") 14 %:pragma GCC optimize("-falign-jumps") 15 %:pragma GCC optimize("-falign-loops") 16 %:pragma GCC optimize("-falign-labels") 17 %:pragma GCC optimize("-fdevirtualize") 18 %:pragma GCC optimize("-fcaller-saves") 19 %:pragma GCC optimize("-fcrossjumping") 20 %:pragma GCC optimize("-fthread-jumps") 21 %:pragma GCC optimize("-funroll-loops") 22 %:pragma GCC optimize("-fwhole-program") 23 %:pragma GCC optimize("-freorder-blocks") 24 %:pragma GCC optimize("-fschedule-insns") 25 %:pragma GCC optimize("inline-functions") 26 %:pragma GCC optimize("-ftree-tail-merge") 27 %:pragma GCC optimize("-fschedule-insns2") 28 %:pragma GCC optimize("-fstrict-aliasing") 29 %:pragma GCC optimize("-fstrict-overflow") 30 %:pragma GCC optimize("-falign-functions") 31 %:pragma GCC optimize("-fcse-skip-blocks") 32 %:pragma GCC optimize("-fcse-follow-jumps") 33 %:pragma GCC optimize("-fsched-interblock") 34 %:pragma GCC optimize("-fpartial-inlining") 35 %:pragma GCC optimize("no-stack-protector") 36 %:pragma GCC optimize("-freorder-functions") 37 %:pragma GCC optimize("-findirect-inlining") 38 %:pragma GCC optimize("-fhoist-adjacent-loads") 39 %:pragma GCC optimize("-frerun-cse-after-loop") 40 %:pragma GCC optimize("inline-small-functions") 41 %:pragma GCC optimize("-finline-small-functions") 42 %:pragma GCC optimize("-ftree-switch-conversion") 43 %:pragma GCC optimize("-foptimize-sibling-calls") 44 %:pragma GCC optimize("-fexpensive-optimizations") 45 %:pragma GCC optimize("-funsafe-loop-optimizations") 46 %:pragma GCC optimize("inline-functions-called-once") 47 %:pragma GCC optimize("-fdelete-null-pointer-checks") 48 49 #include <bits/stdc++.h> 50 using namespace std; 51 52 const int N = 1e5 + 10; 53 54 int dep[N], fa[N], w[N]; 55 56 int n, m, q, dis[N]; 57 58 vector<int> G[N]; 59 60 __attribute__((always_inline)) __attribute__((optimize("O2"))) __attribute__((optimize("O3"))) __inline int get(int x) { return x == fa[x] ? x : get(fa[x]); } 61 62 __attribute__((always_inline)) __attribute__((optimize("O2"))) __attribute__((optimize("O3"))) __inline int merge(int x, int y, int day) { 63 if(dep[x] > dep[y]) swap(x, y); 64 fa[x] = y, w[x] = day, G[y].push_back(x); 65 if(dep[x] == dep[y]) ++ dep[y]; 66 } 67 68 __attribute__((always_inline)) __attribute__((optimize("O2"))) __attribute__((optimize("O3"))) __inline void dfs(int u) { 69 dis[u] = dis[fa[u]] + 1; 70 for(int v: G[u]) dfs(v); 71 } 72 73 template<typename T> __attribute__((always_inline)) __attribute__((optimize("O2"))) __attribute__((optimize("O3"))) __inline void read(T &x) { 74 char c = x = 0; 75 while(!isdigit(c)) c = getchar(); 76 while(isdigit(c)) x = x * 10 + c - '0', c = getchar(); 77 } 78 79 __attribute__((optimize("O2"))) __attribute__((optimize("O3"))) int main() { 80 freopen("pictionary.in", "r", stdin), freopen("pictionary.out", "w", stdout), read(n), read(m), read(q), iota(fa + 1, fa + 1 + n, 1); 81 for(register int i = 1 ; i <= m ; ++ i) 82 for(register int x = m - i + 1, j = x ; j + x <= n ; j += x) { 83 register int u = get(j), v = get(j + x); 84 if(u != v) merge(u, v, i); 85 } 86 for(register int i = 1 ; i <= n ; ++ i) if(fa[i] == i) { dfs(i), fa[i] = 0; break; } 87 for(register int i = 1, u, v ; i <= q ; ++ i) { 88 read(u), read(v); 89 int ans = 0; 90 if(dis[u] < dis[v]) swap(u, v); 91 while(dis[fa[u]] >= dis[v]) ans = max(ans, w[u]), u = fa[u]; 92 if(u != v) { 93 while(fa[u] != fa[v]) ans = max(ans, max(w[u], w[v])), u = fa[u], v = fa[v]; 94 ans = max(ans, max(w[u], w[v])); 95 } 96 printf("%d\n", ans); 97 } 98 }