zoukankan      html  css  js  c++  java
  • POJ 3162 Walking Race(树形dp+单调队列 or 线段树)

    http://poj.org/problem?id=3162

    题意:
    一棵n个节点的树。有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?

    思路:
    这道题目求最远距离和HDU 2196是一模一样的,这个不是很难。关键是要怎么处理得到的数据。

    可以用单调队列做也可以用线段树来做,先介绍一下单调队列。

    因为有最大值和最小值,所以我们需要两个单调队列,一个维护最大值,另一个维护最小值。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,ll> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn=1e6+5;
     17 
     18 int n, m;
     19 int tot;
     20 ll d[maxn][3];
     21 int path[maxn];
     22 int head[2*maxn];
     23 int q_max[maxn];
     24 int q_min[maxn];
     25 
     26 struct node
     27 {
     28     int v,w,next;
     29 }e[2*maxn];
     30 
     31 void addEdge(int u,int v,int w)
     32 {
     33     e[tot].v=v;
     34     e[tot].w=w;
     35     e[tot].next=head[u];
     36     head[u]=tot++;
     37 }
     38 
     39 void dfs1(int u,int fa)
     40 {
     41     d[u][0]=d[u][1]=0;
     42     path[u]=-1;
     43     for(int i=head[u];i!=-1;i=e[i].next)
     44     {
     45         int v=e[i].v;
     46         if(v==fa)  continue;
     47         dfs1(v,u);
     48         if(d[u][0]<d[v][0]+e[i].w)
     49         {
     50             path[u]=v;
     51             d[u][1]=d[u][0];
     52             d[u][0]=d[v][0]+e[i].w;
     53         }
     54         else if(d[u][1]<d[v][0]+e[i].w)
     55             d[u][1]=d[v][0]+e[i].w;
     56     }
     57 }
     58 
     59 void dfs2(int u,int fa)
     60 {
     61     for(int i=head[u];i!=-1;i=e[i].next)
     62     {
     63         int v=e[i].v;
     64         if(v==fa)  continue;
     65         if(path[u]==v)  d[v][2]=max(d[u][2],d[u][1])+e[i].w;
     66         else  d[v][2]=max(d[u][0],d[u][2])+e[i].w;
     67         dfs2(v,u);
     68     }
     69 }
     70 
     71 int main()
     72 {
     73     //freopen("in.txt","r",stdin);
     74     while(~scanf("%d%d",&n,&m))
     75     {
     76         tot=0;
     77         memset(head,-1,sizeof(head));
     78         for(int i=2;i<=n;i++)
     79         {
     80             int v,w;
     81             scanf("%d%d",&v,&w);
     82             addEdge(i,v,w);
     83             addEdge(v,i,w);
     84         }
     85         dfs1(1,-1);
     86         dfs2(1,-1);
     87         int ans=-1;
     88         int frt_max=1,rear_max=1;
     89         int frt_min=1,rear_min=1;
     90         for(int i=1,j=1;i<=n;i++)
     91         {
     92             d[i][0]=max(d[i][0],d[i][2]);
     93             while(frt_max<rear_max && d[q_max[rear_max-1]][0]<d[i][0])  rear_max--;
     94             q_max[rear_max++]=i;
     95             while(frt_min<rear_min && d[q_min[rear_min-1]][0]>d[i][0])  rear_min--;
     96             q_min[rear_min++]=i;
     97 
     98             while(frt_max<rear_max && frt_min<rear_min && d[q_max[frt_max]][0]-d[q_min[frt_min]][0]>m)
     99             {
    100                 if(q_max[frt_max]>q_min[frt_min])   {j=q_min[frt_min]+1;frt_min++;}
    101                 else {j=q_max[frt_max]+1;frt_max++;}
    102             }
    103             ans=max(ans,i-j+1);
    104         }
    105         printf("%d
    ",ans);
    106     }
    107     return 0;
    108 }
    单调队列
      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,ll> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn=1e6+5;
     17 
     18 int n, m;
     19 int tot;
     20 ll d[maxn][3];
     21 int path[maxn];
     22 int head[2*maxn];
     23 
     24 int MAX[maxn<<2];
     25 int MIN[maxn<<2];
     26 int query_max,query_min;
     27 
     28 struct node
     29 {
     30     int v,w,next;
     31 }e[2*maxn];
     32 
     33 void addEdge(int u,int v,int w)
     34 {
     35     e[tot].v=v;
     36     e[tot].w=w;
     37     e[tot].next=head[u];
     38     head[u]=tot++;
     39 }
     40 
     41 /**********************************************
     42 dfs
     43 **********************************************/
     44 
     45 void dfs1(int u,int fa)
     46 {
     47     d[u][0]=d[u][1]=0;
     48     path[u]=-1;
     49     for(int i=head[u];i!=-1;i=e[i].next)
     50     {
     51         int v=e[i].v;
     52         if(v==fa)  continue;
     53         dfs1(v,u);
     54         if(d[u][0]<d[v][0]+e[i].w)
     55         {
     56             path[u]=v;
     57             d[u][1]=d[u][0];
     58             d[u][0]=d[v][0]+e[i].w;
     59         }
     60         else if(d[u][1]<d[v][0]+e[i].w)
     61             d[u][1]=d[v][0]+e[i].w;
     62     }
     63 }
     64 
     65 void dfs2(int u,int fa)
     66 {
     67     for(int i=head[u];i!=-1;i=e[i].next)
     68     {
     69         int v=e[i].v;
     70         if(v==fa)  continue;
     71         if(path[u]==v)  d[v][2]=max(d[u][2],d[u][1])+e[i].w;
     72         else  d[v][2]=max(d[u][0],d[u][2])+e[i].w;
     73         dfs2(v,u);
     74     }
     75 }
     76 
     77 /**********************************************
     78 线段树
     79 **********************************************/
     80 
     81 void PushUp(int o)
     82 {
     83     MAX[o]=max(MAX[o<<1],MAX[o<<1|1]);
     84     MIN[o]=min(MIN[o<<1],MIN[o<<1|1]);
     85 }
     86 
     87 void build(int l, int r, int o)
     88 {
     89     if(l==r)
     90     {
     91         MAX[o]=MIN[o]=max(d[l][0],d[l][2]);
     92         return;
     93     }
     94     int mid=(l+r)/2;
     95     build(l,mid,o<<1);
     96     build(mid+1,r,o<<1|1);
     97     PushUp(o);
     98 }
     99 
    100 void query(int ql, int qr, int l, int r, int o)
    101 {
    102     if(ql<=l && qr>=r)
    103     {
    104         query_max=max(query_max,MAX[o]);
    105         query_min=min(query_min,MIN[o]);
    106         return;
    107     }
    108     int mid=(l+r)/2;
    109     if(ql<=mid)  query(ql,qr,l,mid,o<<1);
    110     if(mid<qr)   query(ql,qr,mid+1,r,o<<1|1);
    111 }
    112 
    113 int main()
    114 {
    115     //freopen("in.txt","r",stdin);
    116     while(~scanf("%d%d",&n,&m))
    117     {
    118         tot=0;
    119         memset(head,-1,sizeof(head));
    120         for(int i=2;i<=n;i++)
    121         {
    122             int v,w;
    123             scanf("%d%d",&v,&w);
    124             addEdge(i,v,w);
    125             addEdge(v,i,w);
    126         }
    127         dfs1(1,-1);
    128         dfs2(1,-1);
    129         build(1,n,1);
    130         int ans=0;
    131 
    132         int l=1,r=1;
    133         while(r<=n)
    134         {
    135             query_max=0; query_min=INF;
    136             query(l,r,1,n,1);
    137             if(query_max-query_min<=m)  {ans=max(ans,r-l+1);r++;}
    138             while(query_max-query_min>m)
    139             {
    140                 l++;
    141                 query_max=0; query_min=INF;
    142                 query(l,r,1,n,1);
    143             }
    144         }
    145         printf("%d
    ",ans);
    146     }
    147     return 0;
    148 }
    线段树
  • 相关阅读:
    团队冲刺第五天
    团队冲刺第一天
    IOS开发(四):开关控件UISwitch
    IOS开发(七):UIActionSheet和UIAlertView
    IOS开发(五):分段控件UISegmentedControl
    [转]IOS开发(一):第一个有交互的APP
    [转]IOS开发(三):UIImageView、UISlider、UIStepper、UIButton
    IOS开发(八):系统声音服务
    [转]Tab Bars和Pickers
    [转]IOS开发(二):ImageView、TextField、键盘
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7349203.html
Copyright © 2011-2022 走看看