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 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    转:浅谈深度学习(Deep Learning)的基本思想和方法
    随记:我们需要怎样的数学教育?
    转 :hlda文献学习笔记
    转:关于Latent Dirichlet Allocation及Hierarchical LDA模型的必读文章和相关代码
    推荐算法相关总结表(包括DM)
    转 自己动手写推荐系统
    求熵 python 代码
    特征值与特征向量
    转: 谱聚类
    链接数据库
  • 原文地址:https://www.cnblogs.com/proverbs/p/2720399.html
Copyright © 2011-2022 走看看