• HDU 4123 Bob’s Race 树的直径+ST表


    Bob’s Race

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://acm.hdu.edu.cn/showproblem.php?pid=4123

    Description

    Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses, and all houses are connected together. To make the race more interesting, he requires that every participant must start from a different house and run AS FAR AS POSSIBLE without passing a road more than once. The distance difference between the one who runs the longest distance and the one who runs the shortest distance is called “race difference” by Bob. Bob does not want the “race difference”to be more than Q. The houses are numbered from 1 to N. Bob wants that the No. of all starting house must be consecutive. He is now asking you for help. He wants to know the maximum number of starting houses he can choose, by other words, the maximum number of people who can take part in his race.
     

    Input

    There are several test cases.
    The first line of each test case contains two integers N and M. N is the number of houses, M is the number of queries.
    The following N-1 lines, each contains three integers, x, y and z, indicating that there is a road of length z connecting house x and house y.
    The following M lines are the queries. Each line contains an integer Q, asking that at most how many people can take part in Bob’s race according to the above mentioned rules and under the condition that the“race difference”is no more than Q.

    The input ends with N = 0 and M = 0.

    (N<=50000 M<=500 1<=x,y<=N 0<=z<=5000 Q<=10000000)

    Output

    For each test case, you should output the answer in a line for each query.

    Sample Input

    5 5
    1 2 3
    2 3 4
    4 5 3
    3 4 2
    1
    2
    3
    4
    5
    0 0

    Sample Output

    1
    3
    3
    3
    5

    HINT

    题意

    一个城镇有N个住户,N-1条路连接两个住户,保证N个住户联通,M次询问,给定N条边的信息,包括连
    接的住户序号以及路的长度。然后是M次询问,每次询问Q,要求找到最长的连续序号(我一开始看成了树上连续一段),使得Max(dis[i]) - Min(dis[i]) ≤
    Q(l≤i≤r),输出最大的r-l+1。dis[i]为从第i个住户出发,不重复走过路能移动的最远距离。

    题解:

    1.首先需要知道一个 结论:树上每个节点理他最远的点肯定是数的直径的两个端点的其中一个。

    2.如果你不会求树的直径以及两个端点,没关系,其实不难,任意找一个点dfs找到离它最远的点root1,root1一定是其中一个端点,然后再以root1为根dfs一遍求出理root1最远的点root2。这样就找到了两个端点。

    3.求出每个点到最远点的距离,我这里是分别以root1,root2 dfs,求出每个点到root1和root2的距离,取个max即可。

    4.题目转化成了,求最长的区间(l,r),满足max{l,r}-min{l,r}<=q。

    5.其实可以用尺取法来做,因为假如(l,r)区间合法,那么(l+1,r)一定合法,那么枚举左端点,右端点只能单增,时间复杂度是O(n)的。

    6.最后要搞个ST表求区间最大最小值。

    我一开始用优先队列做的,然后T了,真是花样作死,非要加个log。

    衷心提示:k=(int)(log(y-x+1)/2)会超时,这个需要预处理,亲测一个1.5s,另一个5.2秒。

    优先队列tle代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define N 50050
      5 int n,m,val[N],dp1[N],dp2[N],flag[N];
      6 int tot,last[N];
      7 struct Edge{int from,to,val,s;}edges[N<<1];
      8 struct Node
      9 {
     10   int id,val;
     11   bool operator <(const Node&b)const
     12   {return val<b.val;}
     13 };
     14 template<typename T>void read(T&x)
     15 {
     16   ll k=0; char c=getchar();
     17   x=0;
     18   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
     19   if (c==EOF)exit(0);
     20   while(isdigit(c))x=x*10+c-'0',c=getchar();
     21   x=k?-x:x;
     22 }
     23 void read_char(char &c)
     24 {while(!isalpha(c=getchar())&&c!=EOF);}
     25 void AddEdge (int x,int y,int z)
     26 {
     27   edges[++tot]=Edge{x,y,z,last[x]};
     28   last[x]=tot;
     29 }
     30 void dfs1(int x,int pre,int &mx,int &root)
     31 {
     32   mx=0; root=x;
     33   int tpmx,tproot;
     34   for(int i=last[x];i;i=edges[i].s)
     35     {
     36       Edge &e=edges[i];
     37       if (e.to==pre)continue;
     38       dfs1(e.to,x,tpmx,tproot);
     39       if (tpmx+e.val>mx)
     40     {
     41       mx=tpmx+e.val;
     42       root=tproot;
     43     }
     44     }
     45 }
     46 void dfs2(int x,int pre,int *dp)
     47 {
     48   for(int i=last[x];i;i=edges[i].s)
     49     {
     50       Edge &e=edges[i];
     51       if (e.to==pre)continue;
     52       dp[e.to]=dp[x]+e.val;
     53       dfs2(e.to,x,dp);
     54     }
     55 }
     56 
     57 void init()
     58 {
     59   read(n); read(m);
     60   if (n==0&&m==0)exit(0);
     61   for(int i=1;i<=n-1;i++)
     62     {
     63       int x,y,z;
     64       read(x); read(y); read(z);
     65       AddEdge(x,y,z);
     66       AddEdge(y,x,z);
     67     }
     68   int maxn=0,root1,root2;
     69   dfs1(1,0,maxn,root1);
     70   dfs1(root1,0,maxn,root2);
     71   dfs2(root1,0,dp1);
     72   dfs2(root2,0,dp2);
     73   for(int i=1;i<=n;i++) val[i]=max(dp1[i],dp2[i]);
     74 }
     75 void solve()
     76 {
     77   int r=0,ans=0,q;
     78   read(q);
     79   priority_queue<Node>Qmx,Qmi;
     80   memset(flag,0,sizeof(flag));
     81   for(int i=1;i<=n;i++)
     82     {
     83       while(r+1<=n&&(Qmx.empty()||
     84            (fabs(val[r+1]-Qmx.top().val)
     85             <=q&&fabs(val[r+1]+Qmi.top().val)<=q)))
     86     {
     87       Qmx.push(Node{r+1,val[r+1]});
     88       Qmi.push(Node{r+1,-val[r+1]});
     89       r++;
     90     }
     91       ans=max(ans,r-i+1);
     92       flag[i]=1;
     93       while(!Qmx.empty()&&flag[Qmx.top().id])Qmx.pop();
     94       while(!Qmi.empty()&&flag[Qmi.top().id])Qmi.pop();
     95     }
     96   printf("%d
    ",ans);
     97 }
     98 void clear()
     99 {
    100   tot=0;
    101   memset(last,0,sizeof(last));
    102   memset(dp1,0,sizeof(dp1));
    103   memset(dp2,0,sizeof(dp2));
    104   memset(flag,0,sizeof(flag));
    105 }
    106 int main()
    107 {
    108 #ifndef ONLINE_JUDGE
    109   freopen("aa.in","r",stdin);
    110 #endif
    111   while(1)
    112     {
    113       clear();
    114       init();
    115       for(int i=1;i<=m;i++) solve();
    116     }
    117 }
    View Code

    ST表AC代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define N 50050
      5 int n,m,dp1[N],dp2[N],mx[N][20],mi[N][20],mm[N];
      6 int tot,last[N];
      7 struct Edge{int from,to,val,s;}edges[N<<1];
      8 template<typename T>void read(T&x)
      9 {
     10   ll k=0; char c=getchar();
     11   x=0;
     12   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
     13   if (c==EOF)exit(0);
     14   while(isdigit(c))x=x*10+c-'0',c=getchar();
     15   x=k?-x:x;
     16 }
     17 void read_char(char &c)
     18 {while(!isalpha(c=getchar())&&c!=EOF);}
     19 void AddEdge (int x,int y,int z)
     20 {
     21   edges[++tot]=Edge{x,y,z,last[x]};
     22   last[x]=tot;
     23 }
     24 void dfs1(int x,int pre,int &mx,int &root)
     25 {
     26   mx=0; root=x;
     27   int tpmx,tproot;
     28   for(int i=last[x];i;i=edges[i].s)
     29     {
     30       Edge &e=edges[i];
     31       if (e.to==pre)continue;
     32       dfs1(e.to,x,tpmx,tproot);
     33       if (tpmx+e.val>mx)
     34     {
     35       mx=tpmx+e.val;
     36       root=tproot;
     37     }
     38     }
     39 }
     40 void dfs2(int x,int pre,int *dp)
     41 {
     42   for(int i=last[x];i;i=edges[i].s)
     43     {
     44       Edge &e=edges[i];
     45       if (e.to==pre)continue;
     46       dp[e.to]=dp[x]+e.val;
     47       dfs2(e.to,x,dp);
     48     }
     49 }
     50 
     51 void init()
     52 {
     53   read(n); read(m);
     54   if (n==0&&m==0)exit(0);
     55   for(int i=1;i<=n-1;i++)
     56     {
     57       int x,y,z;
     58       read(x); read(y); read(z);
     59       AddEdge(x,y,z);
     60       AddEdge(y,x,z);
     61     }
     62   int maxn=0,root1,root2;
     63   dfs1(1,0,maxn,root1);
     64   dfs1(root1,0,maxn,root2);
     65   dfs2(root1,0,dp1);
     66   dfs2(root2,0,dp2);
     67   for(int i=1;i<=n;i++) mx[i][0]=mi[i][0]=max(dp1[i],dp2[i]);
     68 }
     69 void init_ST()
     70 {
     71   mm[0]=-1;
     72   for(int i=1;i<=n;i++)mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1];
     73   for(int i=1;i<=20;i++)
     74     for(int j=1;j+(1<<i)-1<=n;j++)
     75       {
     76     mx[j][i]=max(mx[j][i-1],mx[j+(1<<(i-1))][i-1]);
     77     mi[j][i]=min(mi[j][i-1],mi[j+(1<<(i-1))][i-1]);
     78       }
     79 }
     80 int rmq(int x,int y)
     81 {
     82   int k=mm[y-x+1];
     83   int ans=max(mx[x][k],mx[y-(1<<k)+1][k]);
     84   ans-=min(mi[x][k],mi[y-(1<<k)+1][k]);
     85   return ans;
     86 }
     87 void solve()
     88 {
     89   int r=0,ans=0,q;
     90   read(q);
     91   for(int i=1;i<=n;i++)
     92     {
     93       while(r+1<=n&&rmq(i,r+1)<=q)r++;
     94       ans=max(ans,r-i+1);
     95     }
     96   printf("%d
    ",ans);
     97 }
     98 void clear()
     99 {
    100   tot=0;
    101   memset(last,0,sizeof(last));
    102   memset(dp1,0,sizeof(dp1));
    103   memset(dp2,0,sizeof(dp2));
    104 }
    105 int main()
    106 {
    107 #ifndef ONLINE_JUDGE
    108   freopen("aa.in","r",stdin);
    109 #endif
    110   clock_t now=clock();
    111   while(1)
    112     {
    113       clear();
    114       init();
    115       init_ST();
    116       for(int i=1;i<=m;i++) solve();
    117     }
    118 
    119 }
    View Code
  • 相关阅读:
    无限极分类,递归分类
    foreach加循环体与不加循环体的区别
    图片base64上传时可能遇到的问题
    php(curl请求)测试接口案例
    PHP取得json前面有乱码(去除文件头部BOM)
    PHP计算连续签到天数以及累计签到天数
    原生端与服务器通过sessionid实现session共享以及登录验证
    php安装xunserch
    ROS学习(二)运行keyboard
    ROS学习(一)Ros 中使用kinect
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/10827457.html
Copyright © 2020-2023  润新知