5782. 【NOIP提高A组模拟2018.8.8】 城市猎人

题目大意

有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

Solution

100%:首先分析一下,我们知道在第i天1 * (m - i + 1)….k * (m - i + 1)会相连,于是总的边数就是 n / 1 + n / 2 + n / 3... + n / n
也就是 Σ i = 1 n n i 可以知道这是 n l o g n 级别的,所以可以采取暴力连边,记录一下出现时间,用并查集按秩合并维护,最后询问就是查询两者之间路径的最大值.

时间复杂度:O( n ( l o g n ) 2 )

Code

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 1e6 + 5;

struct ques
{
    int x,y;
}a[N];

struct Edge
{
    int to,val,next;
}edge[N << 1];

int n,m,q,x,y,tot;
int Rank[N],fa[N],st[N],depth[N];

int get(int x)
{
    return fa[x] == x ? x : get(fa[x]);
}

void link(int x,int y,int w)
{
    edge[++tot].val = w;
    if (Rank[x] > Rank[y]) 
    {
        fa[y] = x;
        edge[tot].to = x;
        edge[tot].next = st[y];
        st[y] = tot;
    }
    else
    {
        fa[x] = y;
        edge[tot].to = y;
        edge[tot].next = st[x];
        st[x] = tot;
        if (Rank[x] == Rank[y]) Rank[x]++;
    }
}

int query(int x,int y)
{
    int depx = 0,depy = 0,ret = 0,jx = x,jy = y;
    while (fa[jx] != jx) jx = fa[jx],depx++;
    while (fa[jy] != jy) jy = fa[jy],depy++;
    if (depx < depy) swap(depx,depy),swap(x,y);
    while (depx > depy)
    {
        ret = max(edge[st[x]].val,ret);
        x = fa[x];
        depx--;
    }
    if (x == y) return ret;
    while (x != y)
    {
        ret = max(ret,max(edge[st[x]].val,edge[st[y]].val));
        x = fa[x],y = fa[y];
    }
    return ret;
}

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++) fa[i] = i;
    for (int i = 1 ; i <= m ; i++)
    {
        int t = m - i + 1;
        for (int j = t + t ; j <= n ; j += t) link(get(t),get(j),i);
    }
    for (int i = 1 ; i <= q ; i++) 
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",query(x,y));
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/P_hillipe/article/details/81591713