zoukankan      html  css  js  c++  java
  • HDU 4123 Bob's Race:树的直径 + 单调队列 + st表

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123

    题意:

      给你一棵树,n个节点,每条边有长度。

      然后有m个询问,每个询问给定一个q值。

      设dis[i]为:从节点i出发,不重复经过节点,所能够走的最远距离。

      每次询问问你:区间[l,r]最长能有多长,同时保证 max{dis[i]} - min{dis[i]} <= q (i∈[l,r])

    题解:

      首先有一个结论:

        从树上的任意一个节点出发,尽可能往远走,最终一定会到达树的直径的两个端点之一。

      所以先两遍dfs1,找出直径的两个端点。

      然后分别从两个端点dfs2,求出所有节点的dis[i]。

      因为节点必须选编号连续的一段区间,所以可以用到单调队列。

      枚举每个节点i加入队首。

      然后对于每个i,不断地丢掉队尾pos++,直到当前的区间[pos,i]符合条件。

      那么每次都需要判断是否有 max{dis[i]} - min{dis[i]} <= q (i∈[pos,i])

      这就要用到st表了,然后O(1)判断就好。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <vector>
      5 #define MAX_N 50005
      6 #define MAX_K 20
      7 
      8 using namespace std;
      9 
     10 struct Edge
     11 {
     12     int dest;
     13     int len;
     14     Edge(int _dest,int _len)
     15     {
     16         dest=_dest;
     17         len=_len;
     18     }
     19     Edge(){}
     20 };
     21 
     22 int n,m;
     23 int maxd;
     24 int st,ed;
     25 int dis[MAX_N];
     26 int lg[MAX_N];
     27 int maxt[MAX_N][MAX_K];
     28 int mint[MAX_N][MAX_K];
     29 vector<Edge> edge[MAX_N];
     30 
     31 void read()
     32 {
     33     for(int i=1;i<=n;i++) edge[i].clear();
     34     int x,y,z;
     35     for(int i=1;i<n;i++)
     36     {
     37         cin>>x>>y>>z;
     38         edge[x].push_back(Edge(y,z));
     39         edge[y].push_back(Edge(x,z));
     40     }
     41 }
     42 
     43 void dfs1(int now,int p,int d,int &v)
     44 {
     45     if(d>maxd)
     46     {
     47         maxd=d;
     48         v=now;
     49     }
     50     for(int i=0;i<edge[now].size();i++)
     51     {
     52         Edge temp=edge[now][i];
     53         if(temp.dest!=p) dfs1(temp.dest,now,d+temp.len,v);
     54     }
     55 }
     56 
     57 void dfs2(int now,int p,int d)
     58 {
     59     dis[now]=max(dis[now],d);
     60     for(int i=0;i<edge[now].size();i++)
     61     {
     62         Edge temp=edge[now][i];
     63         if(temp.dest!=p) dfs2(temp.dest,now,d+temp.len);
     64     }
     65 }
     66 
     67 void init_st()
     68 {
     69     lg[0]=-1;
     70     for(int i=1;i<=n;i++)
     71     {
     72         lg[i]=lg[i>>1]+1;
     73         maxt[i][0]=mint[i][0]=dis[i];
     74     }
     75     for(int k=1;(1<<k)<=n;k++)
     76     {
     77         for(int i=1;i+(1<<k)-1<=n;i++)
     78         {
     79             maxt[i][k]=max(maxt[i][k-1],maxt[i+(1<<(k-1))][k-1]);
     80             mint[i][k]=min(mint[i][k-1],mint[i+(1<<(k-1))][k-1]);
     81         }
     82     }
     83 }
     84 
     85 int query_max(int l,int r)
     86 {
     87     int k=lg[r-l+1];
     88     return max(maxt[l][k],maxt[r-(1<<k)+1][k]);
     89 }
     90 
     91 int query_min(int l,int r)
     92 {
     93     int k=lg[r-l+1];
     94     return min(mint[l][k],mint[r-(1<<k)+1][k]);
     95 }
     96 
     97 void work()
     98 {
     99     maxd=-1;
    100     dfs1(1,-1,0,st);
    101     maxd=-1;
    102     dfs1(st,-1,0,ed);
    103     memset(dis,-1,sizeof(dis));
    104     dfs2(st,-1,0);
    105     dfs2(ed,-1,0);
    106     init_st();
    107     while(m--)
    108     {
    109         int q;
    110         cin>>q;
    111         int ans=1;
    112         int pos=1;
    113         for(int i=1;i<=n;i++)
    114         {
    115             while(query_max(pos,i)-query_min(pos,i)>q) pos++;
    116             ans=max(ans,i-pos+1);
    117         }
    118         cout<<ans<<endl;
    119     }
    120 }
    121 
    122 int main()
    123 {
    124     while(cin>>n>>m)
    125     {
    126         if(n==0 && m==0) break;
    127         read();
    128         work();
    129     }
    130 }
  • 相关阅读:
    P4342 [IOI1998]Polygon
    P1194 买礼物
    P1363 幻想迷宫
    Installing Wine 1.5: configure: error: Cannot build a 32-bit program, you need to install 32-bit development libraries(转载)
    Linux系统调用之open(), close() (转载)
    undefined reference to 'pthread_create'问题解决(转载)
    linux中的C里面使用pthread_mutex_t锁(转载)
    #if、#ifdef、#if defined之间的区别(转载)
    linux下解压tgz文件(转载)
    linux修改用户主目录的方法 (转载)
  • 原文地址:https://www.cnblogs.com/Leohh/p/8151330.html
Copyright © 2011-2022 走看看