1.给你一棵边带权的树,求出树中每一个点到其它点的最大距离。
2.在一个整数序列中找一个最大的连续序列,使得该序列中最大数和最小数之差不超过 m 。
问题 1 可用树形 DP 解决。对树进行 DFS,DFS 过程中,对根 R,记录他的孩子结点到他是最大距离和次大距离以及相应的结点。然后用一次 BFS 更新。
问题 2 用两个指针 head, tail分别指向连续序列的首尾,如果区间 [head,tail] 满足条件,则 tail++,更新值最大最小值,不满足条件则 head++, 用线段树更新最大最小值。
注意图不能用 STL 的 vector 和 pair 保存,这样会 TLE。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int const N= 1000010, inf= 0x7fffffff;
int dp[N][2], pos[N][2], flag[N], que[N];
int n, m, cnt;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
struct Edge{
int adj, wt;
Edge* next;
}EG[N<<1];
Edge* mat[N];
struct TB{
int Min, Max;
}tb[N<<2];
inline void add( int u, int v, int d ){
++cnt;
EG[cnt].adj= v; EG[cnt].wt= d;
EG[cnt].next= mat[u]; mat[u]= EG+ cnt;
cnt++;
EG[cnt].adj= u; EG[cnt].wt= d;
EG[cnt].next= mat[v]; mat[v]= EG+ cnt;
}
int dfs( int u ){
dp[u][0]= 0; dp[u][1]= 0; flag[u]= 1;
for( Edge* p= mat[u]; p; p= p->next )
if( !flag[p->adj] ){
int v= p->adj, w= p->wt;
int tmp= w+ dfs( v );
if( tmp> dp[u][0] ){
dp[u][1]= dp[u][0]; pos[u][1]= pos[u][0];
dp[u][0]= tmp; pos[u][0]= v;
}
else if( tmp> dp[u][1] ){
dp[u][1]= tmp; pos[u][1]= v;
}
}
return dp[u][0];
}
void bfs( int rt ){
for( int i= 0; i<= n; ++i ) flag[i]= 0;
int head= 0, tail= 0; que[0]= rt; flag[rt]= 1;
while( head<= tail ){
int u= que[head++];
for( Edge* p= mat[u]; p; p= p->next )
if( !flag[p->adj] ){
int v= p->adj, w= p->wt;
flag[v]= 1; que[++tail]= v;
if( pos[u][0]== v ) w+= dp[u][1];
else w+= dp[u][0];
if( w> dp[v][0] ){
dp[v][1]= dp[v][0]; pos[v][1]= pos[v][0];
dp[v][0]= w; pos[v][0]= u;
}
else if( w> dp[v][1] ){
dp[v][1]= w; pos[v][1]= u;
}
}
}
}
void build( int L, int R, int rt ){
if( L== R ){
tb[rt].Max= tb[rt].Min= dp[L][0]; return; }
int mid= (L+ R)>> 1;
build( L, mid, rt<<1 );
build( mid+ 1, R, rt<<1|1 );
tb[rt].Max= max( tb[rt<<1].Max, tb[rt<<1|1].Max );
tb[rt].Min= min( tb[rt<<1].Min, tb[rt<<1|1].Min );
}
int ansMin, ansMax;
void query( int x, int y, int L, int R, int rt ){
if( L== x && y== R || L== R ){
ansMin= min( ansMin, tb[rt].Min );
ansMax= max( ansMax, tb[rt].Max );
return;
}
int mid= (L+ R)>>1;
if( y<= mid ) query( x, y, L, mid, rt<<1 );
else if( x> mid ) query( x, y, mid+ 1, R, rt<<1|1 );
else{
query( x, mid, L, mid, rt<<1 );
query( mid+ 1, y, mid+ 1, R, rt<<1|1 );
}
}
int main(){
scanf("%d%d",&n,&m ); cnt= -1;
for( int i= 0; i<= n; ++i ){
mat[i]= 0; flag[i]= 0;
}
for( int i= 2; i<= n; ++i ){
int x, y;
scanf("%d%d",&x,&y);
add( i, x, y );
}
dfs(1); bfs(1); build(1,n,1);
int head= 1, tail= 1, ans= 1;
ansMax= dp[1][0], ansMin= dp[1][0];
while( head<= tail && tail<= n ){
if( ansMax- ansMin<= m ){
ans= max( ans, tail- head+ 1 );
tail++;
ansMax= max( ansMax, dp[tail][0] );
ansMin= min( ansMin, dp[tail][0] );
}
else{
++head;
ansMin= inf, ansMax= -inf;
query( head, tail, 1, n, 1 );
}
if( n- head+ 1< ans ) break;
}
printf("%d\n", ans );
return 0;
}
分享到:
相关推荐
ACM PKU_poj 1197 仓库问题源代码,愿与大家共享。若谁更好的代码,多谢提供。
标题“PKU 、POJ ACM/ICPC300多题的代码”指的是北京大学(PKU)和编程在线评测平台POJ上收集的300多道ACM/ICPC(国际大学生程序设计竞赛)比赛题目解题代码。这个压缩包包含了解决这些竞赛问题的算法和程序实现,是...
PKU2104是北京大学的一道算法题目,其提供的源代码着重展示了线段树在“找数据”问题中的应用。 线段树的基本思想是将一个区间分解为若干个子区间,然后对每个子区间构建一棵小树,这些小树通过节点连接形成一个...
标题中的“pku1151.rar_Atlantis_pku 11_poj Atlant_poj Atlantis_poj11”似乎是指北京大学(Peking University, PKU)编程竞赛中的一道题目,编号为1151,与“Atlantis”这个主题相关。这道题目在多个平台上也被提及...
线段树是一种非常有效的数据结构,主要用于解决区间查询和更新的问题,常用于算法竞赛和实际应用中的问题求解。接下来,我们将详细探讨“线段树六题”中各个题目的相关知识点。 ### 1. PKU2352 star2 校门外的树 **...
标题“PKU_poj 1001~1009”揭示了这是一组与北京大学(Peking University)编程竞赛平台POJ相关的解决方案。在这个压缩包中,包含了从问题1001到1009的C++源代码,表明这些代码已经过验证并成功解决了对应的算法问题。...
PKU Online Judge上面很全面的动态规划试题总结。动态规划是ACM考点中最重要的一大类算法之一,对于工作人员来说,动态规划也是实际开发中...这是POJ上面很多DP题目的总结与深刻分析。利于算法学习,学长给的,在此分享
- **技能提升**:项目涉及的数据结构(如二维数组、树形图、向量等)和算法(如字符串处理、文件读写)对于提高编程技能非常有帮助。 - **创新思维**:在解决具体问题时,鼓励学生思考不同的解决方案,培养创新思维...
标题中的“pku_poj_2187.rar_poj 2187_凸包问题”表明这是一个关于北京大学(Peking University, PKU)编程竞赛平台POJ上的第2187题,题目主要涉及凸包问题。描述中的“O(nlogn)凸包问题 poj2187”提示我们解决这个...
### 线段树例题解析 #### Brackets (SPOJ61, BRCKTS) **题目描述:** 此题要求我们维护一个长度为 \(N\) 的小括号序列 \(A\),并支持两种操作: 1. **Replace(i)**:将第 \(i\) 个位置的括号方向反转。 2. **Check...
1011,1012,1013,1014,1015,1017,1026,1028,1032,1035,1041,1046,1129 1149 1154 1165 1182 1185 1190 1191 1201 1251 1273 1275 1276 1286 1322 1338 1363 1364 1401 1456 1459 1564 1579 1637 1657 1658 ...
标题中的“pku1088.rar_pku 10_pku 1088_poj 1088”指的是北京大学(Peking University, PKU)编程竞赛中的第1088题,也称为POJ(Peking University Online Judge)的1088题。这个题目在编程竞赛社区中通常有一个特定的...
树形动态规划(Tree DP)是一种在树结构上进行优化计算的方法,主要应用于解决与树相关的最优化问题。本文将围绕“树形DP问题总结”展开,以“二叉苹果树(ural 1108)”为例,探讨树形DP的思路和应用。 在“二叉...
10. **POJ 2528 线段树.txt**:这是第三个线段树相关的题目,解题报告可能会深入讲解线段树在不同场景下的应用。 通过阅读这些解题报告,你可以学习到各种高级算法的应用,如动态规划、搜索算法、数据结构(如线段...
标题中的"poj3252.rar_pku 3252_poj32"表明这是一个与编程竞赛相关的资源,具体来说是北京大学(PKU)ACM竞赛中的问题3252。"poj"通常指的是"Programming Online Judge",这是一个在线编程比赛平台,而"Pku"则代表...
【标题】"poj 130题 acm pku" 涉及的是ACM(国际大学生程序设计竞赛)中的PKU(北京大学)在线判题系统POJ(Problem Online Judge)的相关题目。ACM/ICPC(International Collegiate Programming Contest)是全球...
北京大学(Peking University, 简称PKU)的POJ(Peking University Online Judge)是一个为计算机科学爱好者和学生提供在线编程训练的平台。这个资源集合了北大POJ初级阶段的所有题目,包含已通过(Accepted, AC)的...
根据提供的文件信息,我们可以分析出该段代码是用于解决POJ平台上的2314题的一种解决方案,主要涉及到了变量管理、表达式处理等方面。下面将详细解释代码中的关键概念和实现逻辑。 ### 关键概念解析 #### Variable...
C http://www.icourse163.org/learn/PKU-1001553023 CC++CC++ http://cxsjsxmooc.openjudge.cn/2017t1summerall/