题意:给出一棵树,两个给给的人在第\(i\)天会从节点\(i\)沿着最长路径走,求最长的连续天数\([L,R]\)使得\([L,R]\)为起点的最长路径极差不超过m

求\(1\)到\(n\)的最长路经可用树形DP求解,

设\(f[i]\):\(i\)的子树下到\(i\)的最远距离

\(g[i]\):\(i\)子树下除了\(f[i]\)子树以外的最远距离

\(h[i]\):除了\(i\)子树以外到\(i\)的最远距离

\(h[i]\)从父到儿子的转移需要判断\(i\)到底是\(fa\)的最远距离所在边还是次远距离所在边(可相等),还有直接来自父亲以上\(h[fa]\)的转移

搞完后求极差就用二分+RMQ强行求出来,注意初始化需要f和h的对比

题目简单但要细心

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define fastIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define println(x) printf("%lld\n",(ll)(x))
using namespace std;
typedef long long ll;
const int MAXN = 1e6+11;
const int MOD = 142857;
const int INF = 1<<30; int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
int cost[MAXN<<1];
int n,m;
void init(int n){memset(head,-1,(n+2)*sizeof(int)),tot=0;}
void add(int u,int v,ll w){
to[tot]=v;
cost[tot]=w;
nxt[tot]=head[u];
head[u]=tot++;
}
int f[MAXN],g[MAXN],h[MAXN];
int mx[MAXN][22],mn[MAXN][22];
void DP0(int u,int fa){
f[u]=g[u]=h[u]=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i]; ll w=cost[i];
if(v==fa) continue;
DP0(v,u);
if(f[v]+w>f[u]){
g[u]=f[u]; //次长子树
f[u]=f[v]+w; //最长子树
}else if(f[v]+w>g[u]){
g[u]=f[v]+w;
}
}
}
void DP1(int u,int fa){
for(int i=head[u];~i;i=nxt[i]){
int v=to[i]; ll w=cost[i];
if(v==fa) continue;
if(f[u]-w==f[v]) h[v]=max(h[u]+w,g[u]+w);//本身v作为儿子是f[u]的最大值,那就从u的次大子树中转移
else h[v]=max(h[u]+w,f[u]+w);
DP1(v,u);
}
}
ll C(int lo,int hi){
int k=log2(hi-lo+1);
return max(mx[lo][k],mx[hi-(1<<k)+1][k])
-min(mn[lo][k],mn[hi-(1<<k)+1][k]);
}
int gao(int st){
int lo=st,hi=n;
while(lo<hi){
int mid=lo+(hi-lo+1)/2;
if(C(st,mid)<=m) lo=mid;
else hi=mid-1;
}
return C(st,lo)?lo:lo-1;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("stdin.txt","r",stdin);
#endif
while(~scanf("%d%d",&n,&m)){
init(n);
for(int i=2;i<=n;i++){
int fi;ll di;
scanf("%d%lld",&fi,&di);
add(i,fi,di);
add(fi,i,di);
}
DP0(1,-1);
DP1(1,-1);
for(int i=1;i<=n;i++){
mx[i][0]=mn[i][0]=max(f[i],h[i]);//f[]只考虑子树内,h[]只考虑子树外
}
int t=log2(n);
for(int i=1;i<=t;i++){
for(int j=1;j<=n;j++){
mx[j][i]=max(mx[j][i-1],mx[j+(1<<i-1)][i-1]);
mn[j][i]=min(mn[j][i-1],mn[j+(1<<i-1)][i-1]);
}
}
int ans=0;
for(int i=1;i<=n;i++){
int hi=gao(i);
ans=max(ans,hi-i+1);
}
println(ans);
}
return 0;
}

BZOJ - 2500 树形DP乱搞的更多相关文章

  1. Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2)(A.暴力,B.优先队列,C.dp乱搞)

    A. Carrot Cakes time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

  2. 2016 10 28考试 dp 乱搞 树状数组

    2016 10 28 考试 时间 7:50 AM to 11:15 AM 下载链接: 试题 考试包 这次考试对自己的表现非常不满意!! T1看出来是dp题目,但是在考试过程中并没有推出转移方程,考虑了 ...

  3. BZOJ 1040 树形DP+环套树

    就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...

  4. BZOJ 4033 树形DP

    http://blog.csdn.net/mirrorgray/article/details/51123741 安利队长blog- 树形dp吧,状态挺显然的,dp[x][j]表示以x为根的子树中,选 ...

  5. BZOJ 4987 (树形DP)

    ###题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4987 ###分析 先考虑贪心,显然k个节点形成一棵树 求出树的直径,显然直径应该只被经 ...

  6. bzoj 3573: [Hnoi2014]米特运输【树形dp+瞎搞】

    阅读理解题,题意是以1为根的有根树,每个点有点权,求修改最少点权能使每个点的权值等于其所有子节点权值之和并且每个点的所有子节点权值相等的个数 然后就比较简单了,就是有个技巧是数太大,需要对所有操作都取 ...

  7. HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)

    考试T2,考试时想到了40pts解法,即对于求b数组,随便瞎搞一下就oxxk,求a的话,很明显的高斯消元,但考试时不会打+没开double挂成10pts(我真sb),感觉考试策略还是不够成熟,而且感觉 ...

  8. bzoj 2217 [Poi2011]Lollipop 乱搞 贪心

    2217: [Poi2011]Lollipop Time Limit: 15 Sec  Memory Limit: 64 MBSec  Special JudgeSubmit: 383  Solved ...

  9. [BZOJ4011][HNOI2015]落忆枫音-[dp乱搞+拓扑排序]

    Description 传送门 Solution 假如我们的图为DAG图,总方案数ans为每个点的入度In相乘(不算1号点).(等同于在每个点的入边选一条边,最后一定构成一棵树). 然而如果加了边x- ...

随机推荐

  1. 【转】简说GNU, GCC and MinGW (Lu Hongling)

    原地址:https://my.oschina.net/u/588967/blog/73478 GNU, GCC, MinGW是开源社区常常要遇到的概念. 网上一般的解释比较繁琐, 让人如坠云雾. 本文 ...

  2. CodeForces 686A Free Ice Cream (水题模拟)

    题意:给定初始数量的冰激凌,然后n个操作,如果是“+”,那么数量就会增加,如果是“-”,如果现有的数量大于等于要减的数量,那么就减掉,如果小于, 那么孩子就会离家.问你最后剩下多少冰激凌,和出走的孩子 ...

  3. Log4Net配置使用简记

    1,引用Log4Net.dll .当前为2.0.8.0版,可添加Nuget包.我的办法是从下载的包中直接引用相应.net版本的dll以减小项目体积 2,在App.config中增加<sectio ...

  4. Android AR平台

    ARToolkit:https://baike.baidu.com/item/ARToolkit/5726883?fr=aladdin Vuforia:搭建Android AR技术开发环境(Aqume ...

  5. 检查路径是否存在与创建指定路径(mfc)

    检查路径是否存在 if (access("D:\\Work\\Encryption\\DES", 0)) 为真,则路径不存在 创建指定路径 system("md D:\\ ...

  6. C++中break/Continue,exit/return的理解

    刚才遇到了一个问题,大概是这样的. func1执行完成,进入func1Complete,其中switch处理func1返回的数据,如果返回数据是clear则重新执行func1. 测试的时候发现func ...

  7. 无线破解那点事(PJ)

    有一段时间没有写博客了.只能说苦逼学生党伤不起啊,还好没挂-废话不说了,近期将会讲讲无线PJ那点事,也不是啥干货,就一些先前的笔记分享把. 0.无线网卡 想要提高破解效率,一块猛一点的USB无线网卡是 ...

  8. iptables 增删查改

    一,安装并启动防火墙 二.添加防火墙规则 1.添加filter表 2.添加nat表 指定位置添加 三.删除iptables规则 四.查看防火墙规则 1.查看filter表 2.查看nat表 五.修改规 ...

  9. C的打印输出格式

    #include<stdio.h> int main() { float test1=12.3224356546565461-0.1; int test2=13; char test3[] ...

  10. delphi中,write和read的用法?什么时候需要用?

    如你所说,在控件或者类的属性中,read 表示 读取,write 则表示设置.比如在类中:TTestClass = (Class)privateFOrderCode:String;publicprop ...