• 51nod 1766 树上的最远点对(线段树)


      像树的直径一样,两个集合的最长路也是由两个集合内部的最长路的两个端点组成的,于是我们知道了两个集合的最长路,枚举一下两两端点算出答案就可以合并了,所以就可以用线段树维护一个区间里的最长路了。

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    #define ll long long
    using namespace std;
    const int maxn=500010,inf=1e9;
    struct tjm{int too,dis,pre;}e[maxn];
    struct poi{int p[3];ll dis;}tree[maxn<<2];
    int n,m,a,b,x,y,z,tot;
    int d[maxn],son[maxn],size[maxn],fa[maxn],top[maxn],last[maxn];
    ll dep[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    void add(int x,int y,int z){e[++tot].too=y;e[tot].dis=z;e[tot].pre=last[x];last[x]=tot;}
    void dfs1(int x)
    {
        size[x]=1;d[x]=d[fa[x]]+1;
        for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
        if(too!=fa[x])
        {   
            dep[too]=dep[x]+e[i].dis;
            fa[too]=x;dfs1(too);
            size[x]+=size[too];
            if(size[too]>size[son[x]])son[x]=too;
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
        if(too!=fa[x]&&too!=son[x])dfs2(too,too);
    }
    int lca(int x,int y)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(d[f1]<d[f2])swap(x,y),swap(f1,f2);
            x=fa[f1];f1=top[x];
        }
        if(d[x]<d[y])swap(x,y);
        return y;
    }
    void pushup(poi x,poi y,ll &dist,int &p1,int &p2)
    {
        if(x.dis>y.dis)dist=x.dis,p1=x.p[1],p2=x.p[2];
        else dist=y.dis,p1=y.p[1],p2=y.p[2];
        for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
        if(x.p[i]&&y.p[j])
        {
            ll dis=dep[x.p[i]]+dep[y.p[j]]-(dep[lca(x.p[i],y.p[j])]<<1);
            if(dis>dist)dist=dis,p1=x.p[i],p2=y.p[j];
        }
    }
    void build(int x,int l,int r)
    {
        if(l==r){tree[x].p[1]=tree[x].p[2]=l;return;}
        int mid=(l+r)>>1;
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        pushup(tree[x<<1],tree[x<<1|1],tree[x].dis,tree[x].p[1],tree[x].p[2]);
    }
    void query(int x,int l,int r,int cl,int cr,ll &dis,int &p1,int &p2)
    {
        if(cl<=l&&r<=cr){dis=tree[x].dis;p1=tree[x].p[1];p2=tree[x].p[2];return;}
        int mid=(l+r)>>1;
        poi t1,t2;t1.dis=t2.dis=-1;t1.p[1]=t1.p[2]=t2.p[1]=t2.p[2]=0;
        if(cl<=mid)query(x<<1,l,mid,cl,cr,t1.dis,t1.p[1],t1.p[2]);
        if(cr>mid)query(x<<1|1,mid+1,r,cl,cr,t2.dis,t2.p[1],t2.p[2]);
        pushup(t1,t2,dis,p1,p2);
    }
    int main()
    {
        read(n);
        for(int i=1;i<n;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
        dfs1(1);dfs2(1,1);
        build(1,1,n);
        read(m);
        for(int i=1;i<=m;i++)
        {
            read(a),read(b),read(x),read(y);
            poi t1,t2;t1.dis=t2.dis=t1.p[1]=t1.p[2]=t2.p[1]=t2.p[2]=0;ll dis;int p1,p2;
            query(1,1,n,a,b,dis,t1.p[1],t1.p[2]);query(1,1,n,x,y,dis,t2.p[1],t2.p[2]);
            pushup(t1,t2,dis,p1,p2);
            printf("%lld
    ",dis);
        }
    }
    View Code
  • 相关阅读:
    IEnumerable 和 IEnumerator 接口
    Asp.net Mvc中使用普通的html超链接的处理
    MVC 3.0 防止跨站点请求伪造 (CSRF) 攻击
    asp.net中表单提交和js注册事件提交表单的先后顺序
    微软依赖注入Unity
    Net序列化JSON序列化
    js中命名空间模式下js方法声明的两个写法
    asp.net中在调用ajax方式去redirect跳转页面??
    asp.net mvc中的post提交方式
    Ambiguous match found:asp.net webform的异常
  • 原文地址:https://www.cnblogs.com/Sakits/p/7684084.html
Copyright © 2020-2023  润新知