zoukankan      html  css  js  c++  java
  • POJ 3162 Walking Race 树形DP+线段树

    给出一棵树,编号为1~n,给出数m

    漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点

    走了n天之后,mm想到知道自己这n天的锻炼效果

    于是mm把这n天每一天走的距离记录在一起,成为一段长度为n的数列

    现在mm想要从这数列中选出一个连续的区间,要求这个区间的max-min<=m

    输出最长的区间

    做了一个下午

    思路:

    分成2个部分:

    1.求出数列,即对于一棵树,求出每一个节点能到达的最远距离

    2.对于这段数列,选出一个区间,使得区间的max-min<=m,并且使得区间长度尽量长。

    对于第1部分,其实就是我昨天做的题目,HDU2196,使用树形DP

    dp[i][1]:表示从i出发到i的子树,能到达的最远距离

    dp[i][2]:表示从i出发到i的子树,能到达的第二远的距离(求dp[i][0]的时候需要用到)

    dp[i][0]:表示从i出发,经过i的父亲节点,能到达的最远距离

    4次dfs,分别求出:

    0.节点的depth,以便把边权(u,v)转化为u,v中depth较大的节点的点权,cost[root]=0;

    1.求出dp[i][1]和son[i],son[i]表示dp[i][1]是通过子节点son[i]这道路径得到的

    2.求出dp[i][2]

    3.求出dp[i][0]

    完成第一部分

    第二部分,前段时间也做过类似的题,HDU5289

    5289要求的是数列中有多少个区间满足条件,我是用RMQ+二分

    这道求的是满足条件的最长区间长度

    我主要时间是花在了解决第二部分

    我刚开始也是用RMQ+二分

    发现mle了

    因为5289的长度n<=1e5,而这道,n<=1e6,所以RMQ开了会mle

    然后我就想改为用线段树代替RMQ的作用,用线段树维护区间的最大值和最小值也很方便,还可以省下很多空间

    然后,tle了

    原因:

    这道题和5289不同的是,这道题不用枚举每一个区间,判断到底满不满足要求

    只要求出一个满足的最长的就好啦

    然后把枚举左端点+二分右端点的代码注释了

    换了种方式:

    用2个指针l,r,

    若区间[l,r]满足条件,r++,同时更新答案

    若不满足条件,l++,直到[l,r]满足条件

    复杂度O(n)

    这就是传说中的尺取法?

    这过程我还犯了一个及其严重的错误:

    求最大值的时候,没有把max_ret初始化为-inf

    求最小值的时候,没有把min_ret初始化为inf

    又花了不少时间

    然后终于过了

      1 #include<cstdio>
      2 #include<cstring>
      3 
      4 using namespace std;
      5 #define lson l,m,rt<<1
      6 #define rson m+1,r,rt<<1|1
      7 
      8 inline int max(int a,int b)
      9 {
     10     return a>b?a:b;
     11 }
     12 
     13 inline int min(int a,int b)
     14 {
     15     return a<b?a:b;
     16 }
     17 
     18 const int maxn=1e6+5;
     19 const int inf=0x3f3f3f3f;
     20 
     21 struct Edge
     22 {
     23     int to,next;
     24 };
     25 Edge edge[maxn<<1];
     26 int head[maxn];
     27 int tot;
     28 int son[maxn];
     29 int dp[maxn][3];
     30 int e[maxn][2];
     31 int dep[maxn];
     32 int cost[maxn];
     33 int seg_max[maxn<<2];
     34 int seg_min[maxn<<2];
     35 int max_ret;
     36 int min_ret;
     37 
     38 void init()
     39 {
     40     memset(head,-1,sizeof head);
     41     tot=1;
     42     memset(dep,0,sizeof dep);
     43     memset(dp,0,sizeof dp);
     44     memset(son,-1,sizeof son);
     45 }
     46 
     47 void addedge(int u,int v)
     48 {
     49     edge[tot].to=v;
     50     edge[tot].next=head[u];
     51     head[u]=tot++;
     52 }
     53 
     54 void solve(int n,int m);
     55 void dfs0(int u,int pre);
     56 void dfs1(int u,int pre);
     57 void dfs2(int u,int pre);
     58 void dfs3(int u,int pre);
     59 void build(int l,int r,int rt);
     60 void pushup(int rt);
     61 int query(int L,int R,int n);
     62 void query_ret(int L,int R,int l,int r,int rt);
     63 
     64 int main()
     65 {
     66     int n,m;
     67     while(~scanf("%d %d",&n,&m))
     68     {
     69         init();
     70         for(int i=2;i<=n;i++)
     71         {
     72             int u,v;
     73             scanf("%d %d",&e[i][0],&e[i][1]);
     74             addedge(i,e[i][0]);
     75             addedge(e[i][0],i);
     76         }
     77         solve(n,m);
     78     }
     79     return 0;
     80 }
     81 
     82 void solve(int n,int m)
     83 {
     84     dfs0(1,-1);
     85     cost[1]=0;
     86     for(int i=2;i<=n;i++)
     87     {
     88         if(dep[i]>dep[e[i][0]])
     89             cost[i]=e[i][1];
     90         else
     91             cost[e[i][0]]=e[i][1];
     92     }
     93     dfs1(1,-1);
     94     dfs2(1,-1);
     95     dfs3(1,-1);
     96     build(1,n,1);
     97     /*
     98     for(int i=1;i<=n;i++)
     99     {
    100         printf("%d
    ",max(dp[i][0],dp[i][1]));
    101     }
    102     */
    103     /*
    104     int ans=0;
    105     for(int i=1;i<=n;i++)
    106     {
    107         int l=i,r=n;
    108         while(r-l>1)
    109         {
    110             int mid=(l+r)>>1;
    111             if(query(i,mid,n)>m)
    112                 r=mid;
    113             else
    114                 l=mid;
    115         }
    116         if(query(i,r,n)<=m)
    117             ans=max(ans,r-i+1);
    118         else
    119             ans=max(ans,l-i+1);
    120     }
    121     */
    122 
    123     int ans=0;
    124     int l=1,r=1;
    125     while(r<=n)
    126     {
    127         while(l<=r&&query(l,r,n)>m)
    128         {
    129             l++;
    130         }
    131         while(r<=n&&query(l,r,n)<=m)
    132         {
    133             ans=max(ans,r-l+1);
    134             r++;
    135         }
    136     }
    137 
    138     printf("%d
    ",ans);
    139     return ;
    140 }
    141 
    142 void dfs0(int u,int pre)
    143 {
    144     for(int i=head[u];~i;i=edge[i].next)
    145     {
    146         int v=edge[i].to;
    147         if(v==pre)
    148             continue;
    149         dep[v]=dep[u]+1;
    150         dfs0(v,u);
    151     }
    152 }
    153 
    154 void dfs1(int u,int pre)
    155 {
    156     for(int i=head[u];~i;i=edge[i].next)
    157     {
    158         int v=edge[i].to;
    159         if(v==pre)
    160             continue;
    161         dfs1(v,u);
    162         if(dp[v][1]+cost[v]>dp[u][1])
    163         {
    164             dp[u][1]=dp[v][1]+cost[v];
    165             son[u]=v;
    166         }
    167     }
    168 }
    169 
    170 void dfs2(int u,int pre)
    171 {
    172     for(int i=head[u];~i;i=edge[i].next)
    173     {
    174         int v=edge[i].to;
    175         if(v==pre)
    176             continue;
    177         dfs2(v,u);
    178         if(v==son[u])
    179             continue;
    180         if(dp[v][1]+cost[v]>dp[u][2])
    181         {
    182             dp[u][2]=dp[v][1]+cost[v];
    183         }
    184     }
    185 }
    186 
    187 void dfs3(int u,int pre)
    188 {
    189     for(int i=head[u];~i;i=edge[i].next)
    190     {
    191         int v=edge[i].to;
    192         if(v==pre)
    193             continue;
    194         if(v==son[u])
    195         {
    196             dp[v][0]=max(dp[u][0],dp[u][2])+cost[v];
    197         }
    198         else
    199         {
    200             dp[v][0]=max(dp[u][0],dp[u][1])+cost[v];
    201         }
    202         dfs3(v,u);
    203     }
    204 }
    205 
    206 void pushup(int rt)
    207 {
    208     seg_max[rt]=max(seg_max[rt<<1],seg_max[rt<<1|1]);
    209     seg_min[rt]=min(seg_min[rt<<1],seg_min[rt<<1|1]);
    210 }
    211 
    212 void build(int l,int r,int rt)
    213 {
    214     if(l==r)
    215     {
    216         seg_max[rt]=seg_min[rt]=max(dp[l][0],dp[l][1]);
    217         return ;
    218     }
    219     int m=(l+r)>>1;
    220     build(lson);
    221     build(rson);
    222     pushup(rt);
    223 }
    224 
    225 int query(int L,int R,int n)
    226 {
    227     max_ret=-inf;
    228     min_ret=inf;
    229     query_ret(L,R,1,n,1);
    230     return max_ret-min_ret;
    231 }
    232 
    233 void query_ret(int L,int R,int l,int r,int rt)
    234 {
    235     if(L<=l&&R>=r)
    236     {
    237         max_ret=max(max_ret,seg_max[rt]);
    238         min_ret=min(min_ret,seg_min[rt]);
    239         return ;
    240     }
    241     int m=(l+r)>>1;
    242     if(L<=m)
    243         query_ret(L,R,lson);
    244     if(R>m)
    245         query_ret(L,R,rson);
    246 }
    View Code
  • 相关阅读:
    JVM源码分析之MetaspaceSize和MaxMetaspaceSize的区别
    JSTREE 实现AJAX重载入时刷新所有节点树
    .NET判断是否为AJAX提交
    防止重复提交的思路
    在使用EF时调用DBFUNCTION扩展方法时,发生ENTITYCOMMANDEXECUTIONEXCEPTION 异常的解决办法
    .NET和JAVA中BYTE的区别以及JAVA中“DES/CBC/PKCS5PADDING” 加密解密在.NET中的实现
    .NET中集合已修改;可能无法执行枚举操作 的解决办法
    ASP.NET中将导出的数据以UTF-8编码方式进行存储
    MVC中的BASE.ONACTIONEXECUTING(FILTERCONTEXT) 的作用
    MVC中部分视图调用方法总结
  • 原文地址:https://www.cnblogs.com/-maybe/p/4745930.html
Copyright © 2011-2022 走看看