2500: 幸福的道路
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 474 Solved: 194
[Submit][Status][Discuss]
Description
小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.
他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.
他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).
他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?
现在,他们把这个艰巨的任务交给你了!
Input
第一行包含两个整数N, M(M<=10^9).
第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.
Output
最长的连续锻炼天数
Sample Input
3 2 1 1 1 3
Sample Output
3
数据范围:
50%的数据N<=1000
80%的数据N<=100 000
100%的数据N<=1000 000
HINT
分析:
比较容易分析的题目。
求每个点的树上最远距离
后面的处理连续天数因为具有传递性是O(n)的。
用优先队列模拟出multiset,总复杂度O(nlogn)
AC代码:
# include <iostream> # include <cstdio> # include <queue> using namespace std; typedef long long LL; const int N = 1e6 + 12; int head[N],dt,n,mn[N],Log[22];LL m,f1[N],f2[N],g[N]; struct Edge{ int to,nex;LL w; }edge[N]; struct Heap{ priority_queue<LL> A,B; void insert(LL x){A.push(x);} void erase(LL x){B.push(x);} void pop(){while(!B.empty() && A.top() == B.top())A.pop(),B.pop();} LL top(){pop();return A.top();} int size(){return A.size() - B.size();} }A,B; void AddEdge(int u,int v,LL w) { edge[++dt] = (Edge){v,head[u],w}; head[u] = dt; } void dfs(int u) { f1[u] = f2[u] = 0; for(int i = head[u];i;i = edge[i].nex) { dfs(edge[i].to); LL tmp = f1[edge[i].to] + edge[i].w; if(tmp >= f1[u]) { f2[u] = f1[u]; f1[u] = tmp; } else f2[u] = max(f2[u],tmp); } } void Dfs(int u) { for(int i = head[u];i;i = edge[i].nex) { if(f1[u] == f1[edge[i].to] + edge[i].w) g[edge[i].to] = max(f2[u],g[u]) + edge[i].w; else g[edge[i].to] = max(f1[u],g[u]) + edge[i].w; Dfs(edge[i].to); } } int main() { scanf("%d %lld",&n,&m);int x;LL y; for(int i = 2;i <= n;i++)scanf("%d %lld",&x,&y),AddEdge(x,i,y); dfs(1);Dfs(1); for(int i = 1;i <= n;i++)g[i] = max(g[i],f1[i]); A.insert(g[1]);B.insert(-g[1]);int r = 2,ans = 0; for(int i = 1;i <= n;i++) { LL mi = r == i ? g[i] : -B.top(),mx = r == i ? g[i] : A.top(); while(r <= n) { mx = max(mx,g[r]); mi = min(mi,g[r]); if(mx - mi <= m)A.insert(g[r]),B.insert(-g[r]),r++; else break; } A.erase(g[i]);B.erase(-g[i]); ans = max(ans,r - i); } printf("%d\n",ans); }