• 题解 幸福的道路


    题意:给定一棵树,将树上每个点的最远距离组成的序列记为{an},在{an}上选出一段连续区间[l,r],用e表示{al…r}的极差,满足e<=M,求出r-l+1的最大值。
    首先注意这道题是连续的,我就被坑了
    首先可以知道要求离每个点的最远距离,可以暴力;
    考虑优化,换根dp;
    首先维护四个数组
    (f[u],fc[u],g[u],gc[u])
    f分别表示以u为根的子树,u的最远距离;
    和不重复的经过另一条边的最远距离;
    g表示以u为起点,u的最远距离;
    和不重复的经过另一条边的最远距离;
    首先暴力算出以一为根的最远距离
    然后换根,看代码
    忘了,最后要求的是连续区间最大差值不超过m的;
    可以同时用最大最小单调队列二维护;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    const int N = 1e6 + 5;
    int n, m, cnt, ans;
    int head[N];
    long long f[N], fc[N], g[N], gc[N], q1[N], q2[N];
    struct edge {
    	int nxt, to, val;
    } e[N << 1];
    
    void add(int x, int y, int z) {
    	e[++cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; e[cnt].val = z;
    }
    
    void dfs(int x, int fa) {
    	for(int i = head[x]; i ; i = e[i].nxt) {
    		int y = e[i].to; if(y == fa) continue;
    		dfs(y, x);
    	}
     	for(int i = head[x]; i ; i = e[i].nxt) {
    		int y = e[i].to; if(y == fa) continue;
    		if(f[x] < f[y] + e[i].val) {
    			fc[x] = f[x];
    			f[x] = max(f[x], f[y] + e[i].val);
    		}
    		else
    			if(fc[x] < f[y] + e[i].val) {
    				fc[x] = max(fc[x], f[y] + e[i].val);
    			}
    	}
    }
    
    void dfs2(int x, int fa, int w) {
    	if(x == 1) {
    		g[1] = f[1]; gc[1] = fc[1];
    		for(int i = head[x]; i ; i = e[i].nxt) {
    			int y = e[i].to; if(y == fa) continue;
    			else dfs2(y, x, e[i].val);
    		}
    	}
    	else {
    		if(f[x] + w != g[fa]) {
    			if(f[x] < w + g[fa]) {
    				g[x] = w + g[fa];
    				gc[x] = f[x];
    			}
    			else {
    				g[x] = f[x];
    				gc[x] = max(fc[x], w + g[fa]);
    			}
    		}
    		else {
    			if(f[x] < w + gc[fa]) {
    				g[x] = w + gc[fa];
    				gc[x] = f[x];
    			}
    			else {
    				g[x] = f[x];
    				gc[x] = max(fc[x], w + gc[fa]);
    			}
    		}
    		for(int i = head[x]; i ; i = e[i].nxt) {
    			int y = e[i].to; if(y == fa) continue;
    			else dfs2(y, x, e[i].val);
    		}
    	}
    }
    
    int main() {
    	
    //	freopen("t3.in","r",stdin); freopen("t3.out","w",stdout);
    	
    	n = read(); m = read();
    	for(int i = 2, x, y;i <= n; i++) {
    		x = read(); y = read();
    		add(i, x, y); add(x, i, y);
    	}
    	
    	dfs(1, 0);
    	dfs2(1, 0, 0);
    	int l1 = 1, r1 = 0, l2 = 1, r2 = 0, t = 1;
    	// for(int i=1;i<=n;i++) cout<<g[i]<<"
    ";
    	for(int i = 1;i <= n; i++)
    	{
    		while(l1 <= r1 && g[q1[r1]] <= g[i]) r1--;
    		q1[++r1] = i;
    		while(l2 <= r2 && g[q2[r2]] >= g[i]) r2--;
    		q2[++r2] = i;
    		while(g[q1[l1]] - g[q2[l2]] > m)
    			if(q1[l1] < q2[l2]) t = q1[l1] + 1, l1++;
    			else t = q2[l2] + 1, l2++;
    		ans = max(ans, i - t + 1);
    	}
    	printf("%d
    ", ans);
    //	cout << endl;
    //	for(int i = 1;i <= n; i++) cout << i << ' ' << f[i] << " " << fc[i] << endl;
    //	cout << endl;
    //	for(int i = 1;i <= n; i++) cout << i << ' ' << g[i] << endl;
    	
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
    /*
    3 2
    1 1
    1 3
    */
    
  • 相关阅读:
    推广项目难点-隐藏IP上
    推广项目难点之数据清洗
    推广项目难点之数据随机分发
    推广项目新架构测试报告
    notepad++正则表达式
    MySQL查询时构建自增ID
    ASP.NET MVC页面UI之多级数据选择UI(行业信息、专业信息、职位信息的选择)
    DesignMode_EasyFactory
    Arithmetic_Thinking -- greedy algorithm
    JDBC--SQL(DDL)
  • 原文地址:https://www.cnblogs.com/Aswert/p/13658780.html
Copyright © 2020-2023  润新知