zoukankan      html  css  js  c++  java
  • 51nod1766 树上的最远点对

    n<=1e5个点的树有边权,m个询问,每次问max dis(i,j) a<=i<=b,c<=j<=d。

    结论:一个区间的最远点对,要么是其左半区间的最远点对,要么是其右半区间的最远点对,要么是左右半区间最远点对的四个点的互相组合之一。如下图:

    两个集合最远点对分别是A-B,A并B的最远点对是红A-蓝B。

    简单证明:一个点到一个点集的最长路径一定是该点到   该点集最远点对这对点的某一点  这样的一条路径。

    比如红点这个集合,从蓝色点到红色点集的最长路。如果X到达A到B这条链遇到的第一个点是A,那么最远就是X到B;如果X到达A到B这条链遇到的第一个点是B,那么最远就是X到A。如果是像上图这种情况,那么最远点对就是X走到B或X走到A。上图的情况中,设X到左上方点距离a,x到AB链遇到的第一个点C距离b,A到C距离c,B到C距离d,C到右下方的点距离e。可以通过不等式简单加减证明。

    所以就用个线段树维护即可,最后把查到两个区间做合并。注意最后一次合并和线段树的合并不一样!!最后的查询问的是两个区间里的点配对,不能把两个点选在同个区间!!

    这题时限比较紧,建议不用倍增求lca,这里用了欧拉序加rmq。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cstdlib>
      5 #include<cmath>
      6 //#include<iostream>
      7 using namespace std;
      8 
      9 struct Mes
     10 {
     11     int s,t,v;
     12 };
     13 int n;
     14 #define maxn 100011
     15 struct Edge{int to,next,v;}edge[maxn<<1];int first[maxn],le=2;
     16 void in(int x,int y,int v) {Edge &e=edge[le];e.to=y;e.v=v;e.next=first[x];first[x]=le++;}
     17 void insert(int x,int y,int v) {in(x,y,v);in(y,x,v);}
     18 int dep[maxn],pos[maxn]; int ll=0,Log[maxn<<1],rmq[maxn<<1][22];
     19 void dfs(int x,int f)
     20 {
     21 //    cout<<x<<endl;
     22     rmq[++ll][0]=x;pos[x]=ll;
     23     for (int i=first[x];i;i=edge[i].next)
     24     {
     25         const Edge &e=edge[i];if (e.to==f) continue;
     26         dep[e.to]=dep[x]+e.v;
     27         dfs(e.to,x);
     28         rmq[++ll][0]=x;
     29     }
     30 }
     31 void pre()
     32 {
     33     dep[0]=dep[1]=0;dfs(1,0);
     34     Log[0]=-1;for (int i=1;i<=ll;i++) Log[i]=Log[i>>1]+1;
     35     for (int j=1;j<=20;j++)
     36         for (int i=1,to=ll-(1<<j)+1;i<=to;i++)
     37             if (dep[rmq[i][j-1]]<dep[rmq[i+(1<<(j-1))][j-1]])
     38                 rmq[i][j]=rmq[i][j-1];
     39             else rmq[i][j]=rmq[i+(1<<(j-1))][j-1];
     40 }
     41 int lca(int x,int y)
     42 {
     43     x=pos[x],y=pos[y];if (x>y) {int t=x;x=y;y=t;}
     44     int l=Log[y-x+1];
     45     return dep[rmq[x][l]]<dep[rmq[y-(1<<l)+1][l]]?rmq[x][l]:rmq[y-(1<<l)+1][l];
     46 }
     47 int dis(int x,int y)
     48 {
     49     int l=lca(x,y);
     50     return dep[x]+dep[y]-2*dep[l];
     51 }
     52 Mes combine(Mes a,Mes b,bool flag)
     53 {
     54     Mes c;c.v=-1;int tmp;
     55     if ((tmp=dis(a.s,b.s))>c.v)
     56     {
     57         c.v=tmp;c.s=a.s;c.t=b.s;
     58     }
     59     if ((tmp=dis(a.s,b.t))>c.v)
     60     {
     61         c.v=tmp;c.s=a.s;c.t=b.t;
     62     }
     63     if ((tmp=dis(a.t,b.s))>c.v)
     64     {
     65         c.v=tmp;c.s=a.t;c.t=b.s;
     66     }
     67     if ((tmp=dis(a.t,b.t))>c.v)
     68     {
     69         c.v=tmp;c.s=a.t;c.t=b.t;
     70     }
     71     if (flag)
     72     {
     73         if (a.v>b.v && a.v>c.v) c=a;
     74         else if (b.v>a.v && b.v>c.v) c=b;
     75     }
     76     return c;
     77 }
     78 struct SMT
     79 {
     80     struct Node
     81     {
     82         Mes m;
     83         int l,r;
     84         int ls,rs;
     85     }a[maxn<<1];
     86     int size;
     87     SMT() {size=0;}
     88     void up(int x)
     89     {
     90         const int &p=a[x].ls,&q=a[x].rs;
     91         a[x].m=combine(a[p].m,a[q].m,1);
     92     }
     93     void build(int &x,int L,int R)
     94     {
     95         x=++size;
     96         a[x].l=L;a[x].r=R;
     97         if (L==R)
     98         {
     99             a[x].ls=a[x].rs=0;
    100             a[x].m.s=L;a[x].m.t=R;
    101             a[x].m.v=0;
    102             return;
    103         }
    104         const int mid=(L+R)>>1;
    105         build(a[x].ls,L,mid);
    106         build(a[x].rs,mid+1,R);
    107         up(x);
    108 //        cout<<a[x].l<<'~'<<a[x].r<<' '<<a[x].m.s<<' '<<a[x].m.t<<' '<<a[x].m.v<<endl;
    109     }
    110     void build()
    111     {
    112         int x;
    113         build(x,1,n);
    114     }
    115     int ql,qr;
    116     Mes query(int x)
    117     {
    118         if (ql<=a[x].l && a[x].r<=qr) return a[x].m;
    119         else
    120         {
    121             const int mid=(a[x].l+a[x].r)>>1;
    122             bool flag=0;Mes ans;
    123             if (ql<=mid) ans=query(a[x].ls),flag=1;
    124             if (qr> mid) ans=flag?combine(ans,query(a[x].rs),1):query(a[x].rs);
    125             return ans;
    126         }
    127     }
    128     Mes query(int L,int R)
    129     {
    130         ql=L;qr=R;
    131         return query(1);
    132     }
    133 }t;
    134 int m,x,y,v,z;
    135 int main()
    136 {
    137     scanf("%d",&n);
    138     for (int i=1;i<n;i++)
    139     {
    140         scanf("%d%d%d",&x,&y,&v);
    141         insert(x,y,v);
    142     }
    143 //    cout<<":)";
    144     pre();
    145 //    cout<<":)";
    146     t.build();
    147 //    cout<<":)";
    148     scanf("%d",&m);
    149 //    cout<<m<<endl;
    150     while (m--)
    151     {
    152         scanf("%d%d%d%d",&x,&y,&v,&z);
    153         Mes ans=combine(t.query(x,y),t.query(v,z),0);
    154         printf("%d
    ",ans.v);
    155     }
    156     return 0;
    157 }
    View Code
  • 相关阅读:
    pig实战 pig常用语法总结,教你快速入门——算法篇
    本科生码农应该会的6种基本排序算法(《数据结构与算法》)
    java 大块内存做数据缓存 大数据的高效收发
    一键安装zookeeper脚本制作篇 相关经验浅谈
    C语言第01次作业顺序、分支结构
    C语言 第三次作业函数
    hashmap笔记
    ArrayList排序与对象的序列化
    插入排序笔记(MIT算法导论课程)
    java解析四则运算表达式
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7648094.html
Copyright © 2011-2022 走看看