题意
给出一棵树,每条边都有一个长度。我们规定每个点的权值为从该点开始走过的一条最长的路径的长度。
求一个最长的区间[l,r],使得[l,r]里面点权的最大值和最小值只差不超过m。
n<=1000000
分析
首先我们要把点权求出来。
那么我们设1为根节点,用两个数组fir[i]和sec[i]维护从节点i开始最长的路径和次长的路径。
第一次先求出起点为i终点在i的子树内的最长路和次长路,第二次再求出每个节点往其父节点走的最长路径。
接着就要求最大的区间,这里我一开始的想法是用数据结构来维护,set或者线段树什么的应该都行,但是我们注意到n<=1000000,则这么干有可能会超时。
那么我们就改用单调栈来维护最大值和最小值。
第一个单调栈保证里面的元素严格递增,第二个单调栈保证里面的元素严格递减,那么最大值就是第二个单调栈的栈底,最小值就是第一个单调栈的栈顶,我们只需要每次插入i时同时维护这两个单调栈即可。
1A大法好!!!
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 1000005
using namespace std;
int n,m,last[N],cnt;
struct edge{
int to,len,next;}e[N*2];
struct stack{
int len,id;}stack1[N],stack2[N];
struct data{
int num,len;}fir[N],sec[N];
void addedge(int u,