码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2500: 幸福的道路(树形dp+单调队列)

时间:2016-08-12 23:21:50      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

好题。。

先找出每个节点的树上最长路

由树形DP完成

节点x,设其最长路的子节点为y

对于y的最长路,有向上和向下两种情况:

down:y向子节点的最长路g[y][0]

up:x的次长路的g[x][1]+dis[x][y]

up:up[fa[x]]+dis[x][y]

dfs1找向下,即向子节点的最长路

dfs2找向上的最长路

最后最长路f[i]=max(up[x],g[x][0])

 

第二部分

找最长连续子序列,使得序列中abs(mx-mn)<=m

这次学习了用单调队列的做法

两个队列mx,mn

mx存单减的f[i]的i,mn单增

由于差值不大于m

每次找出front的最小值出队就行了

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<queue>
 5 #define LL long long
 6 using namespace std;
 7 const int maxn = 1000010;
 8 struct node{
 9     int to,next;
10     LL cost;
11 }e[maxn];
12 int n,m,tot,x;
13 LL g[maxn][2],f[maxn],y,head[maxn];
14 
15 void insert(int u, int v, LL c){
16     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].cost=c;
17 }
18 
19 #define v e[i].to
20 void dfs1(int u){
21     for (int i=head[u]; i!=-1; i=e[i].next){
22         dfs1(v);
23         if (g[u][0]<g[v][0]+e[i].cost){
24             g[u][1]=max(g[u][1],g[u][0]);
25             g[u][0]=g[v][0]+e[i].cost;
26         }else g[u][1]=max(g[u][1],g[v][0]+e[i].cost);
27     }
28 }
29 void dfs2(int u){
30     for (int i=head[u]; i!=-1; i=e[i].next){
31         f[v]=f[u]+e[i].cost;
32         if (g[v][0]+e[i].cost==g[u][0]) f[v]=max(f[v],g[u][1]+e[i].cost);
33         else f[v]=max(f[v],g[u][0]+e[i].cost);
34         dfs2(v);
35     }
36 }
37 
38 int main(){
39     scanf("%d%d", &n, &m);
40     tot=1; memset(head,-1,sizeof(head));
41     for (int i=2; i<=n; i++){
42         int x; LL y;
43         scanf("%d%lld", &x, &y);
44         insert(x,i,y);
45     }
46     dfs1(1);
47     dfs2(1);
48     for (int i=1; i<=n; i++) f[i]=max(f[i],g[i][0]);
49     deque<int> mx,mn;
50     int st=1;
51     int ans=0;
52     for (int i=1; i<=n; i++){
53         while (!mx.empty() && f[mx.back()]<=f[i]) mx.pop_back();
54         while (!mn.empty() && f[mn.back()]>=f[i]) mn.pop_back();
55         mx.push_back(i); mn.push_back(i);
56         while (f[mx.front()]-f[mn.front()]>m){
57             if (mx.front()<mn.front()){
58                 st=mx.front()+1;
59                 mx.pop_front();
60             }
61             else{
62                 st=mn.front()+1;
63                 mn.pop_front();
64             }
65         }
66         ans=max(ans,i-st+1);
67     }
68     printf("%d\n", ans);
69     return 0;
70 }

 

bzoj2500: 幸福的道路(树形dp+单调队列)

标签:

原文地址:http://www.cnblogs.com/mzl120918/p/5766693.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!