• 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) = m - i + 1 的点对连边,由于要求的是最早联通时间,之前已经联通则不管后面的边,我们用并查集维护一下连通性即可

    这样最后会变成一棵树,暴力枚举 m - i + 1 的倍数建边即可,树边上记录联通时间

    每个询问的答案就是路径 x--lca(x, y)--y 上的边权的最大值

    发现根本不用建树,在并查集上按秩合并维护树的形态即可,这样最大深度是 log 级别的,lca 也就不用倍增什么的了 = =

    暴力乱搞就行了

    由于是用并查及维护的信息,需要及时 findfa 更新必要的信息


    代码:
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    using namespace std;
    
    const int MAXN = 100005;
    
    int n, m, q, blk;
    int fa[MAXN], siz[MAXN], d[MAXN], dep[MAXN];
    
    int findfa(int x) {
    	if(fa[x] != x) dep[x] = dep[fa[x]] + 1;
    	else return x;
    	return findfa(fa[x]);
    }
    inline void link(int x, int y, int v) {
    	int fx = findfa(x), fy = findfa(y);
    	if(fx == fy) return;
    	--blk;
    	if(siz[fx] <= siz[fy]) {
    		d[fx] = v;
    		fa[fx] = fy;
    		siz[fy] += siz[fx];
    		findfa(fy);
    	} else {
    		d[fy] = v;
    		fa[fy] = fx;
    		siz[fx] += siz[fy];
    		findfa(fx);
    	}
    	return;
    }
    inline int query(int xx, int yy) {
    	findfa(xx); findfa(yy);
    	if(dep[yy] > dep[xx]) swap(xx, yy);
    	int res = 0;
    	while(dep[xx] != dep[yy]) {
    		res = max(res, d[xx]);
    		xx = fa[xx];
    	}
    	while(xx != yy) {
    		res = max(res, max(d[xx], d[yy]));
    		xx = fa[xx];
    		yy = fa[yy];
    	}
    	return res;
    }
    
    int main() {
    	freopen("pictionary.in", "r", stdin);
    	freopen("pictionary.out", "w", stdout);
    	scanf("%d%d%d", &n, &m, &q);
    	blk = n;
    	for(int i = 1; i <= n; ++i) {fa[i] = i; siz[i] = 1;}
    	for(int i = 1; i <= m; ++i) {
    		int cur = m - i + 1, mul = 2, last = m - i + 1;
    		while(cur * mul <= n) {
    			link(last, cur * mul, i);
    			last = cur * mul;
    			++mul;
    			if(blk == 1) break;
    		}
    		if(blk == 1) break;
    	}
    	register int xx, yy;
    	while(q--) {
    		scanf("%d%d", &xx, &yy);
    		printf("%d
    ", query(xx, yy));
    	}
    	return 0;
    }
    

      

     
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    Web上传大文件的解决方案
    JS上传大文件的解决方案
    网页上传大文件的解决方案
    B/S上传大文件的解决方案
    Unity UGUI——提供可视功能的UI组件(Text)
    Java设计模式透析之 —— 策略(Strategy)
    【边做项目边学Android】小白会遇到的问题--Appcompat_V7问题
    高度平衡树 -- AVL 树
    成长这事儿,不可不说-------Day36
    Cocos2D-X2.2.3学习笔记5(UI系统)
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9445834.html
Copyright © 2020-2023  润新知