码迷,mamicode.com
首页 > 其他好文 > 详细

loj6145 Easy

时间:2019-03-28 09:27:22      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:front   turn   char   描述   分治   name   ++   pen   pac   

题目描述:

给一棵树,$q$次询问,每次给出$l$,$r$,$x$,求点$x$到$l$,$l+1$……$r$距离的最小值。

题解:

动态点分治。

考虑树上任意一条路径经过的最高级重心只能有一个,我们可以先建出点分树,在点分树上的每个节点存当前子树所有节点到该节点距离的最小值。

对于每次查询,可以让$x$延点分树向上跳,相当于枚举路径的最高级重心。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100050;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){c=c*10+ch-0;ch=getchar();}
    x = f*c;
}
int n,hed[N],cnt;
struct EG
{
    int to,nxt,w;
}e[2*N];
void ae(int f,int t,int w)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    e[cnt].w = w;
    hed[f] = cnt;
}
int RT[N];
struct segtree
{
    int ls[150*N],rs[150*N],mn[150*N],tot;
    void insert(int l,int r,int &x,int d,int k)
    {
        if(!x)x=++tot,mn[x]=0x3f3f3f3f;
        mn[x]=min(mn[x],k);
        if(l==r)return ;
        int mid = (l+r)>>1;
        if(d<=mid)insert(l,mid,ls[x],d,k);
        else insert(mid+1,r,rs[x],d,k);
    }
    int query(int l,int r,int u,int ql,int qr)
    {
        if(!u)return 0x3f3f3f3f;
        if(l==ql&&r==qr)return mn[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,ls[u],ql,qr);
        else if(ql>mid)return query(mid+1,r,rs[u],ql,qr);
        else return min(query(l,mid,ls[u],ql,mid),query(mid+1,r,rs[u],mid+1,qr));
    }
}tr;
int ff[N],sum,siz[N],fs[N],rt,rot,Dis[N];
bool mrk[N];
int dep[N],dis[N],son[N],top[N],fa[N];
void dfs1(int u,int f)
{
    fa[u] = f;
    siz[u] = 1;
    dep[u] = dep[f]+1;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to==f)continue;
        dis[to]=dis[u]+e[j].w;
        dfs1(to,u);
        siz[u]+=siz[to];
        if(siz[to]>siz[son[u]])
            son[u]=to;
    }
}
void dfs2(int u,int Top)
{
    top[u]=Top;
    if(!son[u])return ;
    dfs2(son[u],Top);
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to!=fa[u]&&to!=son[u])
            dfs2(to,to);
    }
}
int get_lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x = fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y)
{
    return dis[x]+dis[y]-2*dis[get_lca(x,y)];
}
void dfs(int u,int f)
{
    siz[u] = 1,fs[u] = 0;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to==f||mrk[to])continue;
        dfs(to,u);
        siz[u]+=siz[to];
        fs[u] = max(fs[u],siz[to]);
    }
    fs[u] = max(fs[u],sum-siz[u]);
    if(fs[u]<fs[rt])rt=u;
}
int vis[N],tmp[N];
void bfs()
{
    queue<int>q;
    q.push(rt);
    tr.insert(1,n,RT[rt],rt,0);
    vis[rt] = rt,tmp[rt] = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to]||vis[to]==rt)continue;
            tmp[to] = tmp[u]+e[j].w;
            tr.insert(1,n,RT[rt],to,tmp[to]);
            vis[to]=rt;
            q.push(to);
        }
    }
}
int get_rt(int u)
{
    rt = 0;
    dfs(u,0);
    bfs();
    mrk[u=rt] = 1;
    for(int j=hed[rt];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(mrk[to])continue;
        sum = siz[to];
        int nxt = get_rt(to);
        ff[nxt] = u;
        Dis[nxt] = get_dis(nxt,u);
    }
    return u;
}
int main()
{
//    freopen("tt.in","r",stdin);
    read(n);
    for(int f,t,w,i=1;i<n;i++)
    {
        read(f),read(t),read(w);
        ae(f,t,w),ae(t,f,w);
    }
    dfs1(1,0),dfs2(1,1);
    fs[0] = 0x3f3f3f3f;
    sum = n;
    rot=get_rt(1);
    int q;
    read(q);
    for(int l,r,x,i=1;i<=q;i++)
    {
        read(l),read(r),read(x);
        int ans = tr.query(1,n,RT[x],l,r);
        int x0 = x;
        while(ff[x])
        {
            x = ff[x];
            ans = min(ans,tr.query(1,n,RT[x],l,r)+get_dis(x0,x));
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

loj6145 Easy

标签:front   turn   char   描述   分治   name   ++   pen   pac   

原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10612667.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!