题目链接:

The Elder

题意:

给定一棵树,根节点为1,每条边都有一个权值。节点 i 到节点 j 的花费为这两点间路径权值和的平方。现在从每个点到根节点,可以在路径的任何点停留,每次停留cost+=这两点间路径权值和的平方+P(最后一步跳到根节点不需要+P),使该cost最小化。最后求所有点的cost的最大值。

思路:

每个点到根节点都是一条唯一路径:

设dp[i]:表示节点 i 到根节点的花费的最小值。

设sum[i]:表示路径上权值的前缀和。

  (0<=j<i)

复杂度O(n^2),对该路径上的权值进行斜率dp优化O(n):

设 j>k,且 j 优于 k :

设x=sum[i],y=dp[i]+sum[i]^2,上述不等式左边即为斜率。

可知:

当  时,

j 优于 k 且 j 优于 i 。

因此维护一个下凸

因为sum[i]单调递增,所以维护单调队列,每次找到第一个 j 和 j+1 的斜率>2sum[i],j 即为最佳跳转点。

本题最关键的点在于单调队列的还原。如果树的每条链都单独计算,会有很多重复计算的边,复杂度会远超O(n)。因此需要回溯到一个点的时候把单调队列还原。

做法是dfs树的时候给每个点一个dfs序。维护一个栈,当单调队列里有点被弹出了,就把该点在单调队列的位置,值和被弹出的时间戳压入栈。当回溯到该点时,把栈中dfs序在该点之后的点还原,再把单调队列此时的 left 和 right 还原。

因为最后一步跳到根节点不需要+P,所以按上述式子多算了一次P,答案剪掉即可。

Code:

#include<bits/stdc++.h>
using namespace std;typedef long long ll;
const int MAX = 2e5 + 50;typedef struct {int to, val;
}Point;typedef struct {int pos;int val;int time;
}Node;int n, p;
vector<Point>mp[MAX];
ll dp[MAX], sum[MAX];
int Left, Right;
int q[MAX];
int dfstime;
stack<Node>s;ll up(int j, int k) {return (dp[j] + sum[j] * sum[j]) - (dp[k] + sum[k] * sum[k]);
}ll down(int j, int k) {return (sum[j] - sum[k]);
}void dfs(int root, int fa)
{int nowtime = ++dfstime;while (Left < Right&&up(q[Left + 1], q[Left]) <= 2 * sum[root] * down(q[Left + 1], q[Left]))Left++;int front = q[Left];dp[root] = dp[front] + (sum[root] - sum[front])*(sum[root] - sum[front]) + p;while (Left < Right&&up(q[Right], q[Right - 1])*down(root, q[Right]) >= up(root, q[Right])*down(q[Right], q[Right - 1])) {s.push(Node{ Right,q[Right],nowtime });Right--;}q[++Right] = root;int le = Left, re = Right;for (int i = 0; i < mp[root].size(); i++) {if (mp[root][i].to == fa)    continue;sum[mp[root][i].to] = sum[root] + mp[root][i].val;Left = le, Right = re;while (!s.empty()) {Node tmp = s.top();if (tmp.time <= nowtime)    break;q[tmp.pos] = tmp.val;s.pop();}dfs(mp[root][i].to, root);}return;
}int main()
{int T;scanf("%d", &T);while (T--){while (!s.empty())s.pop();scanf("%d%d", &n, &p);for (int i = 0; i <= n; i++)mp[i].clear();for (int i = 1; i < n; i++) {int u, v, w;scanf("%d%d%d", &u, &v, &w);mp[u].push_back(Point{ v, w });mp[v].push_back(Point{ u, w });}dfstime = 0;dp[1] = 0;sum[1] = 0;Left = 1, Right = 1;q[1] = 1;int le = Left, re = Right;for (int i = 0; i < mp[1].size(); i++) {sum[mp[1][i].to] = sum[1] + mp[1][i].val;Left = le, Right = re;while (!s.empty()) {s.pop();}dfs(mp[1][i].to, 1);}ll ans = 0;for (int i = 1; i <= n; i++) {ans = max(ans, dp[i] - p);}printf("%lld\n", ans);}return 0;
}

The Elder(hdu 5956 树上斜率dp + 队列还原)相关推荐

  1. The Elder HDU - 5956

    /* 树上斜率优化 一开始想的是构造出一个序列 转化成一般的dp但是可能被卡 扫把状的树的话可能变成n*n 其实可以直接在树上维护这个单调队列 dfs虽然搞得是一棵树,但是每次都是dfs到的都是一个序 ...

  2. HDU 3669 Cross the Wall(斜率DP+预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669 题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得 ...

  3. hdu 3480 斜率dp

    思路:很普通的斜率dp #include<cstdio> #include<cstring> #include<iostream> #include<algo ...

  4. HDU 3094 树上删边 NIM变形

    基本的树上删边游戏 写过很多遍了 /** @Date : 2017-10-13 18:19:37* @FileName: HDU 3094 树上删边 NIM变形.cpp* @Platform: Win ...

  5. bzoj 3437: 小P的牧场(斜率DP)

    3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1493  Solved: 830 [Submit][Status][Disc ...

  6. HDU - 5242 Game(树形dp+树链剖分/树上贪心+思维)

    题目链接:点击查看 题目大意:给出一棵包含n个节点的树,每个节点都有一个权值,整棵树的根是点1,问从点1开始向下一直走到叶子节点,可以走k次,怎么样走权值和最大,每个节点被走过一次后权值会变为0 题目 ...

  7. HDU 5378 树上的概率DP Leader in Tree Land

    官方题解: 可以用求概率的思想来解决这个问题.令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]个点.那么第i个点是第i棵子树最大值的概率为1/sz[i],不是最大值的概率为(sz[i]- ...

  8. bzoj1492 [NOI2007]货币兑换Cash (斜率DP+cdq分治)

    题意:到处都找得到. 我没看错的话当年考试的时候的题面里头,是提示了买卖一定是全部买入和卖出的.这样一来就好办了.cdq的论文里面那个F并不是她所说的那样,而是就是那个最优值.方程转移的时候实际上是枚 ...

  9. HDU 2196 Computer 树形DP经典题

    链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问 ...

  10. HDU 5148 Cities 树形DP(背包)

    HDU 5148 题意;n个点的树,第i条边长度为c[i],任意选中k个点为特殊点,这k个点中,任意两点间距离的期望值最小为多少? n<=2000,k<=min(50,n) c[i]< ...

最新文章

  1. 距离传感器控制灯泡代码_如何使用颜色传感器和超声波传感器检测障碍物和避障...
  2. Word英文字符间距太大 中英文输入切换都不行
  3. 三层交换的HSRP与VRRP
  4. js map 箭头_JS异常函数之-箭头函数
  5. 近期 AI 领域招聘招生信息汇总
  6. 【ElasticSearch】ElasticSearch 7.8 IK 同义词 配置
  7. C++单元测试工具CppUnit使用简介 【转载】
  8. Linux 串口驱动与使用
  9. 算法竞赛入门经典第11章 无根树转有根树
  10. 【PS4开发】如何通过unity3d发布ps4应用
  11. 贵州大学计算机学院研究生成绩查询,贵州大学计算机科学与技术学院2008年硕士研究生初试、复试总成绩一览表...
  12. 人脸识别-特征脸方法
  13. yaml文件的加载使用
  14. 我的世界1.14java原版命令_我的世界1.14.4第一个预览版发布 添加了debugreport命令...
  15. 创立达摩院,马云是想当武林盟主吗?
  16. 皮卡丘(pikachu)敏感信息泄露
  17. 在主窗口中打开一个子窗口,主窗口和子窗口怎么传递参数?
  18. Nexus 05 第二种方式 使用Jenkins Nexus插件上传制品
  19. 找素数(质数):线性筛法和埃氏筛法
  20. 这些前端案例看似很简单(内附动图)

热门文章

  1. 使用两个路由器级连实现共用一个宽带
  2. in作为介词的用法_英语介词丨in、on 、at 的具体用法到底有哪些?
  3. 华为手机怎么隐藏按键图标_你的华为手机隐藏功能,待激活
  4. Windows无法调节显示亮度
  5. 身份证读卡器 护照阅读器,如何能做到读取多证件呢?
  6. web.py mysql_webpy连接mysql出现问题
  7. 考考你、智商题 小明借爸爸500元 又借妈妈500元 买双鞋 970元 还剩30元 还给爸爸10元...
  8. 练习4-10 找出最小值 (20分) 本题要求编写程序,找出给定一系列整数中的最小值。
  9. finecms aip.php漏洞,代码审计| FineCMS的GetShell姿势
  10. 苹果服务器 显示器,苹果M1芯片的Mac可以外接什么显示器 显示器最高支持多少分辨率...