zoukankan      html  css  js  c++  java
  • POJ 4003 树形DP+RMQ

    题意:

    一颗树,得到每个节点可到达的最远路径长度组成的序列,每给定一个q,求最长满足{最大值-最小值<=q}的连续序列的长度

    分析:

    ①求以每个节点出发的最长路径

    dfs+树形dp:

    dfs出从u节点出发,向下延伸的最长路径的长度dis[u],以及是从那条边向下延伸得到的disnum[u],还有u节点向下延伸的次长路pis[u]

    从上向下DP,找到dp[u]表示从u向父节点延伸的最长路径长度

    (如果这个还不熟练请移步:HDU 2196,就是求步骤①)

    ②维护区间最大最小的差

    维护一个队列(虚拟的,真实存在的只是 h 队头指针 ,t  队尾指针 两个指针),若当前h~t不满足条件h++

    否则t++

    用rmq O(1)算出最值

    PS:log不预处理出来会TLE,TLE两次,再度听WZC神犇说log巨慢无比,改成预处理就AC了~

    XLk神犇说单纯的单调队列可以做,表示我这蒟蒻不会。。。

    View Code
      1 #include <cstdio>
      2 #include <cmath>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 #define N 50010
      9 #define M 5000000
     10 
     11 using namespace std;
     12 
     13 int to[M],next[M],len[M],head[N],cnt,dis[N],pis[N],ans[N],dp[N],fin,disnum[N],qu,n,m;
     14 int pmax[N][20],pmin[N][20],lg[N*2];
     15 
     16 inline void add(int u,int v,int w)
     17 {
     18     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     19 }
     20 
     21 void dfs(int u,int pre)
     22 {
     23     dis[u]=pis[u]=0;
     24     for(int i=head[u];~i;i=next[i])
     25         if(pre!=to[i])
     26         {
     27             dfs(to[i],u);
     28             if(dis[u]<dis[to[i]]+len[i])
     29             {
     30                 dis[u]=dis[to[i]]+len[i];
     31                 disnum[u]=to[i];
     32             }
     33         }
     34     for(int i=head[u];~i;i=next[i])
     35         if(pre!=to[i]&&disnum[u]!=to[i])
     36             if(pis[u]<dis[to[i]]+len[i])
     37                 pis[u]=dis[to[i]]+len[i];
     38 }
     39 
     40 void find(int u,int pre)
     41 {
     42     for(int i=head[u];~i;i=next[i])
     43         if(to[i]!=pre)
     44         {
     45             if(to[i]==disnum[u]) dp[to[i]]=max(dp[u],pis[u])+len[i];
     46             else dp[to[i]]=max(dp[u],dis[u])+len[i];
     47             find(to[i],u);
     48         }
     49 }
     50 
     51 int maxrmq(int l,int r)
     52 {
     53     int k=lg[r-l+1];
     54     return max(pmax[l][k],pmax[r-(1<<k)+1][k]);
     55 }
     56 
     57 int minrmq(int l,int r)
     58 {
     59     int k=lg[r-l+1];
     60     return min(pmin[l][k],pmin[r-(1<<k)+1][k]);
     61 }
     62 
     63 void pretend()
     64 {
     65     scanf("%d",&qu);
     66     fin=0;
     67     int h=1,t=1;
     68     while(h<=t&&t<=n)
     69     {
     70         if(maxrmq(h,t)-minrmq(h,t)<=qu)
     71         {
     72             fin=max(fin,t-h+1);
     73             t++;
     74         }
     75         else h++;
     76     }
     77     printf("%d\n",fin);
     78 }
     79 
     80 void init_rmq()
     81 {
     82     for(int i=1;i<=n;i++)
     83         pmax[i][0]=pmin[i][0]=ans[i];
     84     for(int j=1;(1<<j)<=n;j++)
     85         for(int i=1;i+(1<<j)-1<=n;i++)
     86         {
     87             pmax[i][j]=max(pmax[i][j-1],pmax[i+(1<<(j-1))][j-1]);
     88             pmin[i][j]=min(pmin[i][j-1],pmin[i+(1<<(j-1))][j-1]);
     89         }
     90 }
     91 
     92 void go()
     93 {
     94     memset(disnum,-1,sizeof disnum);
     95     memset(dp,-1,sizeof dp);
     96     dfs(1,-1);
     97     dp[1]=0;
     98     find(1,-1);
     99     for(int i=1;i<=n;i++) ans[i]=max(dp[i],dis[i]);
    100     init_rmq();
    101     for(int i=1;i<=m;i++) pretend();
    102 }
    103 
    104 void read()
    105 {
    106     memset(head,-1,sizeof head); cnt=0;
    107     for(int i=1,a,b,c;i<n;i++)
    108     {
    109         scanf("%d%d%d",&a,&b,&c);
    110         add(a,b,c),add(b,a,c);
    111     }
    112 }
    113 
    114 int main()
    115 {
    116     for(int i=1;i<100000;i++)
    117         lg[i]=(i>>lg[i-1]+1)?lg[i-1]+1:lg[i-1];
    118     while(scanf("%d%d",&n,&m),n||m)
    119     {
    120         read();
    121         go();
    122     }
    123     //system("pause");
    124     return 0;
    125 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    codeforces 980A Links and Pearls
    zoj 3640 Help Me Escape
    sgu 495 Kids and Prizes
    poj 3071 Football
    hdu 3853 LOOPS
    hdu 4035 Maze
    hdu 4405 Aeroplane chess
    poj 2096 Collecting Bugs
    scu 4444 Travel
    zoj 3870 Team Formation
  • 原文地址:https://www.cnblogs.com/proverbs/p/2720399.html
Copyright © 2011-2022 走看看