zoukankan      html  css  js  c++  java
  • [51nod] 1766 树上的最远点对

    1766 树上的最远点对 

    基准时间限制:3 秒 空间限制:524288 KB 分值: 80  难度:5级算法题

     
     
    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
    Analysis
    洛谷秋令营讲解过的题目,因此并没有用很多时间进行深刻的思考
    基本构架:线段树,用于处理区间询问
    首先我们有A B两个点集,从A B中各取一个点以组成最远点对,求出其距离
    首先可以有这一个结论:最后的最远点对的点,在A中的,必然也是A中最远点对的其中一个点
    因此线段树维护每个区间的最远点对,当区间合并的时候取他们各自的最远点对暴力取优即可
    (百度一发题解,有人指出最远点对的合并与树的直径的合并具有相似性,因此得出上面的结论)
    (但是本蒟蒻很迷啊)
    好,接下来谈实现
    1. 线段树!
    首先线段树基本框架没有问题,我们需要实现一个函数:合并(merge)
    这里推荐在单点区间内把最远点对的两个点都设成自己(第一个坑)
    不然合并的时候爆炸(我将不存在的点设成了-1结果qwq)
    最后的答案要求从A B各取一个点,所以合并函数还需要注意:线段树内的合并可以从单个集合中取点对,而最终答案不行
    2. 求距离!
    要求求出最近公共祖先(然后瞎搞)
    倍增LCA,TLE最后6个点
    虽然我没怎么卡常数而且写的非常粗糙(比如没有记忆化每次都要重新求)
    但是显然这是算法问题
    所以找CCZ求得了一个O(1)LCA的方案
    orz ccz!
    首先求出当前树的欧拉序(不同于DFS序的是,这里的欧拉序要求包括每一次进入的结点)

    然后对于这份DFS序,我们要做的就是:求出区间(以U V的随便哪个DFN值做区间端点)的最小值(这里的区间保存的是深度Depth)所对应的那个点
    显然,那个点就是U V的LCA
    而使用ST表的话可以做到O(1)查询
    qwq 然而我没学ST表啊 qwq
    所以最后跑去看了qt666的博客
    qwq (其实代码中的ST表代码是无缝移植qt666的,表示感谢!)
    (找个时间还是要重写一遍的,一是不大好无缝移植,趁早学会重造比较好,二是各种调试代码太多)
    (敲这道题的时候我居然没有重写)
    Code
      1 #include<stdio.h>
      2 #include<iostream>
      3 #define maxn 1000000
      4 #define lc (rt<<1)
      5 #define rc (rt<<1|1)
      6 #define mid ((L+R)/2)
      7 using namespace std;
      8 
      9 int dfn[maxn],dfnn[maxn],TIM,line[maxn],chain[maxn],sum[maxn];
     10 int pre[maxn],pre2[maxn],ST[maxn][30];
     11 int fa[maxn][20],ro[maxn][20],depth[maxn],n,m;
     12 
     13 struct edge{ int from,u,v,len; }e[maxn];
     14 int tot,first[maxn];
     15 void insert(int u,int v,int len){ tot++; e[tot].from = first[u], e[tot].u = u , e[tot].v = v , e[tot].len = len, first[u] = tot; }
     16 
     17 void dfs(int now){
     18     dfn[now] = ++TIM;
     19     line[TIM] = -depth[now];
     20     chain[TIM] = now;
     21     for(int i = first[now];i;i = e[i].from){
     22         int v = e[i].v;
     23         if(v != fa[now][0]){
     24             sum[v] = sum[now]+e[i].len;
     25             depth[v] = depth[now]+1;
     26             fa[v][0] = now;
     27 //            ro[v][0] = e[i].len;
     28             dfs(v);
     29             line[++TIM] = -depth[now];
     30             chain[TIM] = now;
     31         }
     32     }
     33 }
     34 void Init(){
     35     for(int i = 1;i <= 18;i++)
     36     for(int j = 1;j <= n;j++)
     37         fa[j][i] = fa[fa[j][i-1]][i-1],
     38         ro[j][i] = ro[fa[j][i-1]][i-1]+ro[j][i-1];
     39 }
     40 
     41 void makeST()
     42 {
     43   pre[0]=1;for(int i=1;i<=20;i++) pre[i]=pre[i-1]<<1;
     44   pre2[0]=-1;for(int i=1;i<=TIM;i++) pre2[i]=pre2[i>>1]+1;
     45   for(int i=1;i<=TIM;i++) ST[i][0]=i;
     46   for(int j=1;j<=20;j++)
     47     for(int i=1;i<=TIM;i++){
     48       if(i+pre[j]-1<=TIM){
     49        int x1=ST[i][j-1],x2=ST[i+pre[j-1]][j-1];
     50        if(line[x1]>line[x2]) ST[i][j]=x1;
     51        else ST[i][j]=x2;
     52       }
     53     }
     54 }int queryST(int l,int r)
     55 {
     56     l = dfn[l],r = dfn[r];
     57     if(l > r) swap(l,r);
     58 //    printf("query:[%d , %d]
    ",l,r);
     59   if(l==r)return chain[l];
     60   int x=pre2[r-l+1];
     61   int x1=ST[l][x],x2=ST[r-pre[x]+1][x];
     62   return line[x1]>line[x2]?chain[x1]:chain[x2];
     63 }
     64 
     65 int getdis(int u,int v){
     66     if(depth[u] < depth[v]) swap(u,v);
     67     int anc = queryST(u,v);
     68     if(anc == v) return sum[u]-sum[anc];
     69     else return sum[u]+sum[v]-sum[anc]*2;
     70     /*int ret = 0;
     71     if(depth[u] < depth[v]) swap(u,v);
     72     for(int i = 18;i >= 0;i--)
     73         if(depth[fa[u][i]] >= depth[v])
     74             ret += ro[u][i],
     75             u = fa[u][i];
     76     if(u == v) return ret;
     77     for(int i = 18;i >= 0;i--)
     78         if(fa[u][i] != fa[v][i])
     79             ret += ro[u][i]+ro[v][i],
     80             u = fa[u][i],v = fa[v][i];
     81     return ret + ro[u][0] + ro[v][0];*/
     82 }
     83 struct node{ int A,B; node(){A = B = -1;}}Tree[maxn*4];
     84 node merge(node a,node b,int mode){
     85     node tmp;
     86 //    printf("What I get: a.A%d a.B%d b.A%d b.B%d
    ",a.A,a.B,b.A,b.B);
     87     int dis = -1;
     88     if(a.A > 0 && a.B > 0 && mode){
     89         int cnt = getdis(a.A,a.B);
     90         if(cnt > dis) dis = cnt,tmp.A = a.A,tmp.B = a.B;
     91     }if(a.A > 0 && b.A > 0){
     92         int cnt = getdis(a.A,b.A);
     93         if(cnt > dis) dis = cnt,tmp.A = a.A,tmp.B = b.A;
     94     }if(a.A > 0 && b.B > 0){
     95         int cnt = getdis(a.A,b.B);
     96         if(cnt > dis) dis = cnt,tmp.A = a.A,tmp.B = b.B;
     97     }if(a.B > 0 && b.A > 0){
     98         int cnt = getdis(a.B,b.A);
     99         if(cnt > dis) dis = cnt,tmp.A = a.B,tmp.B = b.A;
    100     }if(a.B > 0 && b.B > 0){
    101         int cnt = getdis(a.B,b.B);
    102         if(cnt > dis) dis = cnt,tmp.A = a.B,tmp.B = b.B;
    103     }if(b.A > 0 && b.B > 0 && mode){
    104         int cnt = getdis(b.A,b.B);
    105         if(cnt > dis) dis = cnt,tmp.A = b.A,tmp.B = b.B;
    106 //        cout << "Who visit me qwq?" << endl;
    107     }
    108 //    cout << "dis: " << dis << endl;
    109     
    110     return tmp;
    111 }
    112 
    113 void build(int rt,int L,int R){
    114     if(L == R) Tree[rt].A = L,Tree[rt].B = L;
    115     else{
    116         build(lc,L,mid);
    117         build(rc,mid+1,R);
    118         
    119         Tree[rt] = merge(Tree[lc],Tree[rc],1);
    120     }
    121 //    printf("#%d: L%d R%d A%d B%d
    ",rt,L,R,Tree[rt].A,Tree[rt].B);
    122 }
    123 
    124 node query(int rt,int L,int R,int qL,int qR){
    125     if(qL <= L && R <= qR) return Tree[rt];
    126     else{
    127         node tmp;
    128         if(qL <= mid) tmp = merge(tmp,query(lc,L,mid,qL,qR),1);
    129         if(qR > mid) tmp = merge(tmp,query(rc,mid+1,R,qL,qR),1);
    130 //        printf("tmp now is: %d %d
    ",tmp.A,tmp.B);
    131         return tmp;
    132     }
    133 }
    134 
    135 int read(){
    136     int ret = 0; char ctr = getchar();
    137     while(ctr < '0' || ctr > '9') ctr = getchar();
    138     while(ctr >= '0' && ctr <= '9') ret = ret*10+ctr-'0',ctr = getchar();
    139     return ret;
    140 }
    141 
    142 int main(){
    143 //    scanf("%d",&n);
    144     n = read();
    145     for(int i = 1;i < n;i++){
    146         int x,y,z; //scanf("%d%d%d",&x,&y,&z);
    147         x = read(),y = read(),z = read();
    148         insert(x,y,z); insert(y,x,z);
    149     }depth[1] = 1; dfs(1); Init();
    150     makeST();
    151 //    printf("dis(1,3) %d
    ",getdis(1,3));
    152 //    scanf("%d",&m);
    153     m = read();
    154 //    for(int i = 0;i <= TIM;i++){
    155 //    for(int j = 0;j <= 9;j++)
    156 ////        printf("%d ",ST[i][j]);
    157 //        cout << endl;
    158 //    }
    159 //    for(int i = 0;i <= TIM;i++) printf("%d ",line[i]); cout << endl;
    160 //    for(int i = 0;i <= TIM;i++) printf("%d ",chain[i]);
    161 //    printf("LCA %d dis(3,4) = %d sum3 %d sum4 %d
    ",queryST(3,4),getdis(3,4),sum[3],sum[4]);
    162 //    printf("LCA of :%d %d = %d
    ",1,4,query(1,4));
    163     build(1,1,n);
    164     while(m--){
    165         int a,b,c,d;
    166 //        scanf("%d%d%d%d",&a,&b,&c,&d);
    167         a = read(),b = read(),c = read(),d = read();
    168 //        cout << "AAA";
    169         node ans = merge(query(1,1,n,a,b),query(1,1,n,c,d),0);
    170 //        cout << "AAA";
    171 //        cout << "Great" << ans.A << ans.B << endl;
    172         printf("%d
    ",getdis(ans.A,ans.B));
    173     }
    174     
    175 //    for(int i = 0;i <= 20;i++)
    176 //        printf("#%d: %d %d
    ",i,Tree[i].A,Tree[i].B);    
    177     return 0;
    178 }
    qwq
    
    
  • 相关阅读:
    bug的约束
    bug管理规范
    FTP小教程
    测试需求,产品需求,项目需求
    如何理解客户需求、市场需求、产品需求、业务需求、特性、功能需求 ?(转)
    什么是测试需求?(转)
    绑定与非绑定,反射,内置方法
    面向对象之组合、封装、多态、property装饰器
    面向对象之继承与派生,属性查找
    面向对象基础
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7637081.html
Copyright © 2011-2022 走看看