Xenia and Tree CodeForces - 342E

http://codeforces.com/problemset/problem/342/E

可以假设所有红点都给定了不会再变 然后求与某个蓝点最近的红点的距离 这样直接BFS一遍就好啊

但是这里有修改 肯定不可能每改一次都跑一遍BFS 这时就要用到分块法 即每累积sqrt(n)次修改就统一大改一次 碰到查询时就先o(1)看之前大改后求得的最短距离 然后再和累积的小修改都求一下最短距离 树上最短距离就用lca

因为求lca是logn 所以可以把累积次数放小一点 防止偏沉

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int v;
    int next;
};

node edge[400010];
int dp[200010][20];
int que[200010];
int first[200010],deep[200010],red[200010],dis[200010],book[200010];
int n,q,num,head,tail;

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfs(int cur,int fa)
{
    int i,v;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa)
        {
            dp[v][0]=cur;
            deep[v]=deep[cur]+1;
            dfs(v,cur);
        }
    }
    return;
}

void solve()
{
    int i,j;
    dp[1][0]=0;
    deep[1]=1;
    dfs(1,0);
    for(j=1;(1<<j)<=n;j++)
    {
        for(i=1;i<=n;i++)
        {
            dp[i][j]=dp[dp[i][j-1]][j-1];
        }
    }
    return;
}

int getlca(int u,int v)
{
    int i;
    if(deep[u]<deep[v]) swap(u,v);
    for(i=log2(n);i>=0;i--)
    {
        if(deep[dp[u][i]]>=deep[v])
        {
            u=dp[u][i];
        }
    }
    if(u==v) return u;
    for(i=log2(n);i>=0;i--)
    {
        if(dp[u][i]!=dp[v][i])
        {
            u=dp[u][i];
            v=dp[v][i];
        }
    }
    return dp[u][0];
}

void bfs()
{
    int i,u,v;
    memset(book,0,sizeof(book));
    for(i=head;i<=tail;i++) book[que[i]]=1;
    while(head<=tail)
    {
        u=que[head];
        head++;
        for(i=first[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(book[v]==0&&dis[v]>dis[u]+1)
            {
                que[++tail]=v;
                dis[v]=dis[u]+1,book[v]=1;
            }
        }
    }
    head=1,tail=0;
}

void init()
{
    memset(dis,0x3f,sizeof(dis));
    head=1,tail=0;
    que[++tail]=1;
    red[1]=1,dis[1]=0;
    bfs();
}

int main()
{
    int i,tp,u,v,lca,ans;
    scanf("%d%d",&n,&q);
    memset(first,-1,sizeof(first));
    num=0;
    for(i=1;i<=n-1;i++)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    solve();
    init();
    while(q--)
    {
        scanf("%d%d",&tp,&u);
        if(tp==1)
        {
            if(red[u]==0)
            {
                que[++tail]=u;
                red[u]=1,dis[u]=0;
                if(tail-head+1==100) bfs();
            }
        }
        else
        {
            ans=dis[u];
            for(i=head;i<=tail;i++)
            {
                lca=getlca(u,que[i]);
                ans=min(ans,deep[u]+deep[que[i]]-2*deep[lca]);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82423337
今日推荐