• 51nod 1766 树上的最远点对


    基准时间限制:3 秒 空间限制:524288 KB
     
    n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j<=d}
    (PS 建议使用读入优化)
    Input
    第一行一个数字 n n<=100000。
    第二行到第n行每行三个数字描述路的情况, x,y,z (1<=x,y<=n,1<=z<=10000)表示x和y之间有一条长度为z的路。
    第n+1行一个数字m,表示询问次数 m<=100000。
    接下来m行,每行四个数a,b,c,d。
    Output
    共m行,表示每次询问的最远距离
    Input示例
    5
    1 2 1
    2 3 2
    1 4 3
    4 5 4
    1
    2 3 4 5
    Output示例
    10
    -----
    解:线段树,ST表,lca

    这题需要一个结论

    设集合A中的最远点对为u,v

    集合B中的最远点对为p,q

    那么集合 A并B 的最远点对为u,v,p,q中的两个(即C(4,2)==6)

    证明类似树的直径的证明

    ===

    写到心态崩,重写了好几次;

    rmq&lca 写了好几次,看不懂别人的,只自己用个结构体弄;

    线段树的pushup函数崩了好多次,好像是因为p=l.u还是p=l.v的问题(但我不认为这样会有问题);

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using std::swap;
    using std::min;
    const int N=200017;
    inline int read()  
    {  
        int ans=0,f=1;char t=getchar();  
        while(t<'0'||t>'9')   f=(t=='-'?-1:1),t=getchar();  
        while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();  
        return ans*f;  
    }  
    int dep[N],tar[N],dfn[N],book[N],dis[N],line[N];
    struct node
    {
        int from,to,next,p;
    }e[N];
    int first[N];
    int cnt=0;
    void insert(int u,int v,int p)
    {
        e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].p=p;
        e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;e[cnt].p=p;
    }
    void dfs(int x)
    {
        dfn[++cnt]=x,tar[x]=cnt,line[cnt]=dep[x];book[x]=1;
        for(int i=first[x];i;i=e[i].next)
        {        
            if(!book[e[i].to])
            {        
                dis[e[i].to]=dis[x]+e[i].p;    
                dep[e[i].to]=dep[x]+1;
                dfs(e[i].to);            
                line[++cnt]=dep[x];    
                dfn[cnt]=x;
            }
        }
    }
    struct flagg
    {
        int dp,zi;
    }f[N<<1][27];
    int lg[N<<1];
    inline int lca(int l,int r)  
    {  
        l=tar[l],r=tar[r];  
        if(l>r)  swap(l,r); 
        int t=lg[r-l+1];  
        int x,y;
        x=f[l][t].dp,y=f[r-(1<<t)+1][t].dp;
        if(x<=y) return f[l][t].zi;    
        else     return f[r-(1<<t)+1][t].zi;
     //   if(line[a].depth<=line[b].depth) return line[a].zi;
      //  else return line[b].zi;
      //  printf("%%%%   %d
    ",t);    
    //    if(ans==f[l][t]) return dfn[l];
    //    else return dfn[r-(1<<t)+1];
    }  
    struct edgt
    {
        int l,r,v,u,dis;
    }tr[N<<2];
    #define ll ro<<1
    #define rr ro<<1|1 
    const int inf=1e9+12;
    inline int getdis(int u,int v)
    {
        return dis[u]+dis[v]-(dis[dfn[lca(u,v)]]<<1);
    }
    inline void pushup(edgt &ro,edgt l,edgt r,int flag)  
    {  
        bool tag1=( (l.l==l.r) &&l.l>0),tag2=( (r.l==r.r) && (r.l>0) );  
        int ans=0,tt=0,i=0,j=0;
        if(tag1&&!tag2)  
        {          
            if(flag) if(r.dis>ans)    ans=r.dis,i=r.u,j=r.v;  
              
            tt=getdis(l.u,r.u);  
            if(tt>ans)   ans=tt,i=l.u,j=r.u;          
            tt=getdis(l.u,r.v);  
            if(tt>ans)   ans=tt,i=l.u,j=r.v;            
            ro.dis=ans,ro.u=i,ro.v=j;  
        }  
        else if(!tag1&&tag2)  
        {          
            if(flag) if(l.dis>ans)    ans=l.dis,i=l.u,j=l.v;  
              
            tt=getdis(l.u,r.u);  
            if(tt>ans)   ans=tt,i=l.u,j=r.u;            
            tt=getdis(l.v,r.u);  
            if(tt>ans)   ans=tt,i=l.v,j=r.u;  
            ro.dis=ans,ro.u=i,ro.v=j;  
        }  
        else if(tag1&&tag2)  
        {  
            ro.u=l.l;ro.v=r.l;  
            ro.dis=getdis(ro.u,ro.v);   
        }  
        else   
        {          
            if(flag) if(l.dis>ans)    ans=l.dis,i=l.u,j=l.v;  
            if(flag) if(r.dis>ans)    ans=r.dis,i=r.u,j=r.v;  
            
            tt=getdis(l.u,r.u);  
            if(tt>ans)   ans=tt,i=l.u,j=r.u;            
            tt=getdis(l.u,r.v);  
            if(tt>ans)   ans=tt,i=l.u,j=r.v;        
            tt=getdis(l.v,r.u);  
            if(tt>ans)   ans=tt,i=l.v,j=r.u;            
            tt=getdis(l.v,r.v);  
            if(tt>ans)   ans=tt,i=l.v,j=r.v;           
            ro.dis=ans,ro.u=i,ro.v=j;  
        }  
    }  
    void build(int ro,int l,int r)
    {
        tr[ro].l=l,tr[ro].r=r;
        if(l==r)
        {
            tr[ro].v=tr[ro].u=l;
            tr[ro].dis=-inf;
            return;
        }
        int mid=(l+r)>>1;
        build(ll,l,mid);
        build(rr,mid+1,r);
        pushup(tr[ro],tr[ll],tr[rr],1);
    }
    edgt query(int ro,int l,int r)  
    {  
        if(l<=tr[ro].l&&tr[ro].r<=r)      return tr[ro];  
        int mid=(tr[ro].l+tr[ro].r)>>1;  
        if(r<=mid)   return query(ll,l,r);  
        else if(l>mid)   return query(rr,l,r);  
        else  
        {  
            edgt ans;  
            edgt a=query(ll,l,mid),b=query(rr,mid+1,r);  
            pushup(ans,a,b,1);  
            return ans;  
        }  
    }  
    int main()
    {
        int n;
        n=read();
        int v,u,p;
        for(int i=1;i<n;i++) v=read(),u=read(),p=read(),insert(v,u,p);
        dep[1]=1;
        cnt=0;
        dfs(1);
    //    for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    //    for(int i=1;i<=n;i++) printf("%d ",dep[i]);
    //    printf("*********
    ");
    //    for(int i=1;i<=cnt;i++)
    //        printf("std:: i : %d line : %d tar : %d dfn : %d
    ",i,line[i],tar[i],dfn[i]);
        //lca&rmq:
        lg[1]=0;  
        for(int i=2;i<=cnt;i++)      lg[i]=lg[i>>1]+1;   
        for(int i=1;i<=cnt;i++)  f[i][0].dp=line[i],f[i][0].zi=i;  
          
        int x,y;
        for(int j=1;j<=22;j++)  
        for(int i=1;i<=cnt-( 1<<(j -1) );i++)
        {
            x=f[i][j-1].dp,y=f[ i+( 1<< (j-1) )][ j-1 ].dp;
            if(x<=y) f[i][j].dp=x,f[i][j].zi=f[i][j-1].zi;        
            else     f[i][j].dp=y,f[i][j].zi=f[ i+( 1<< (j-1) )][ j-1 ].zi;
        }     
    //    printf("std:: %d",lca(1,3));   
        //tree:
        build(1,1,n);
    //    for(int i=1;i<=20;i++)
    //        printf("tree:: %d %d %d %d %d
    ",tr[i].l,tr[i].r,tr[i].v,tr[i].u,tr[i].dis);
    //    printf("std:: %d 
    ",getdis(3,5)); 
           int m=read();
           int a,b,c,d;
           for(int i=1;i<=m;i++)
           {
              a=read(),b=read(),c=read(),d=read();
              edgt x=query(1,a,b),y=query(1,c,d),ans;
      //        printf("lca:: a,b: %d c,d: %d
    ",dfn[lca(a,b)],dfn[lca(c,d)]);
           pushup(ans,x,y,0);
           printf("%d
    ",ans.dis); 
           }
        return 0;
    }
    View Code
  • 相关阅读:
    OCS 2007 R2单机测试虚拟环境的搭建(windows server 2008 R2 x64)
    Linq的概念解析
    WCF Data Service与net.tcp承载分析
    codeplex上20个有意思的WPF程序
    各种SmartPhone上的跨平台开源框架的总结
    新开发Apple Store上软件的实施步骤
    VSTO应用程序中加入键盘钩子
    绝非偶然 苹果iPhone领先5年背后的迷思 【推荐】
    Windows上安装Mac OS虚拟机
    Visual Studio 远程调试的步骤
  • 原文地址:https://www.cnblogs.com/12fs/p/7672603.html
Copyright © 2020-2023  润新知