「NOI2014」购票
「NOI2014」购票
解题思路
先列出 \(dp\) 式子并稍微转化一下
dp[u]=\min(dp[v]+dis[v]\times p[u]) + p[u]\times dis[u]+q[u] \\
\]
假设有 \(dis(v2)< dis(v1)\) 且 \(p(u)\) 在 \(v2\) 的取值比 \(v1\) 优,可以得到斜率式
\dfrac{dp(v2) -dp(v1)}{dis(v2)-dis(v1)}\geq p(u)
\]
利用 \(cdq\) 的思想对有根树进行点分治,每次计算分治中心 \(H\) 到其祖先的一条链对其它联通块的贡献,维护一个凸包在凸包上二分即可,还挺好写的,复杂度 \(\mathcal O(n\log^2n)\) 。
code
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf ((ll)(1e18))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define int ll
const int N = 2000005;
vector<int> g[N];
int dis[N], dep[N], lim[N], dp[N], d[N], Q[N], p[N], pa[N];
int A[N], sz[N], vis[N], pq[N], q[N], n, mn, rt, all, cnt;
inline double slope(int x, int y){
return (double) (dp[y] - dp[x]) / (double) (dis[y] - dis[x]);
}
inline bool cmp(int x, int y){
return dis[x] - lim[x] > dis[y] - lim[y];
}
inline void update(int x, int y){
dp[x] = min(dp[y] + (dis[x] - dis[y]) * p[x] + q[x], dp[x]);
}
inline void prework(int u, int fa){
pa[u] = fa, dep[u] = dep[fa] + 1, dis[u] = dis[fa] + d[u];
for(int i = 0; i < (int) g[u].size(); i++)
if(g[u][i] != fa) prework(g[u][i], u);
}
inline void getsize(int u, int fa){
int mson = 0; sz[u] = 1;
for(int i = 0; i < (int) g[u].size(); i++){
int v = g[u][i];
if(vis[v] || v == fa) continue;
getsize(v, u), sz[u] += sz[v];
if(sz[v] > mson) mson = sz[v];
}
mson = max(mson, all - sz[u]);
if(mson < mn) mn = mson, rt = u;
}
inline void dfs(int u, int fa){
A[++cnt] = u;
for(int i = 0; i < (int) g[u].size(); i++)
if(!vis[g[u][i]] && g[u][i] != fa) dfs(g[u][i], u);
}
inline void divtree(int u, int top){
vis[u] = 1; int lst = all;
for(int i = 0; i < (int) g[u].size(); i++){
int v = g[u][i];
if(!vis[v] && v == pa[u]){
mn = all = sz[v] > sz[u] ? lst - sz[u] : sz[v];
getsize(v, u), divtree(rt, top);
}
}
for(int s = pa[u]; s != pa[top]; s = pa[s])
if(dis[u] - dis[s] <= lim[u]) update(u, s);
cnt = 0;
for(int i = 0; i < (int) g[u].size(); i++){
int v = g[u][i];
if(!vis[v]) dfs(v, u);
}
sort(A + 1, A + cnt + 1, cmp);
int t = 0; int s = u;
for(int i = 1; i <= cnt; i++){
while(s != pa[top] && dis[A[i]] - lim[A[i]] <= dis[s]){
while(t > 1 && slope(Q[t-1], Q[t]) <= slope(Q[t-1], s)) t--;
Q[++t] = s, s = pa[s];
}
int l = 1, r = t - 1, res = 1;
while(l <= r){
int mid = (l + r) >> 1;
if(slope(Q[mid], Q[mid+1]) >= (double) p[A[i]])
res = l = mid + 1;
else r = mid - 1;
}
if(res <= t) update(A[i], Q[res]);
}
for(int i = 0; i < (int) g[u].size(); i++){
int v = g[u][i];
if(vis[v]) continue;
mn = all = sz[v] > sz[u] ? lst - sz[u] : sz[v];
getsize(v, u), divtree(rt, v);
}
}
signed main(){
read(n); int type; read(type);
for(int i = 2, x; i <= n; i++){
read(x), read(d[i]), read(p[i]);
read(q[i]), read(lim[i]), dp[i] = inf;
g[x].push_back(i), g[i].push_back(x);
}
prework(1, 0);
mn = all = n, getsize(1, 0), divtree(rt, 1);
for(int i = 2; i <= n; i++) printf("%lld\n", dp[i]);
return 0;
}
「NOI2014」购票的更多相关文章
- 「NOI2014」购票 解题报告
「NOI2014」购票 写完了后发现写的做法是假的...然后居然过了,然后就懒得管正解了. 发现需要维护凸包,动态加点,询问区间,强制在线 可以二进制分组搞,然后你发现在树上需要资瓷撤回,然后暴力撤回 ...
- LOJ#2249 Luogu P2305「NOI2014」购票
几乎肝了半个下午和整个晚上 斜率优化的模型好多啊... LOJ #2249 Luogu P2305 题意 给定一棵树,第$ i$个点如果离某个祖先$ x$的距离不超过$ L_i$,可以花费$ P_i· ...
- LOJ 2249: 洛谷 P2305: 「NOI2014」购票
题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...
- LOJ 2249: 洛谷 P2305: bzoj 3672: 「NOI2014」购票
题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...
- 【LOJ】#2244. 「NOI2014」起床困难综合症
题解 写水题放松一下心情 二进制有个很好的性质是每一位是独立的,我们按位贪心,先看这一位能不能填1,然后看看如果这一位填0那么运算后最后这一位是不是1,是的话就退出,然后看看这一位如果填1最后是1这一 ...
- 「NOI2014」魔法森林
题目链接 戳我 \(Solution\) 两个变量,emm...不好搞啊. 于是我们可以按照\(A\)排序.然后动态加边,因为\(A\)是越来越大,所以不需要管他,只要使得\(1\)~\(n\)的路径 ...
- LOJ#2244. 「NOI2014」起床困难综合症
$n \leq 1e5$个位运算操作,$m \le 2^{30}$,问$0-m$中谁进行完所有操作值最大,输出这个最大值. cfA题难度?当送分题就不管了 and相当于几个位取0,or相当于几个位取1 ...
- 「NOI2014」动物园
link : https://loj.ac/problem/2246 水水KMP #include<bits/stdc++.h> #define ll long long #define ...
- LG2375/LOJ2246 「NOI2014」动物园 KMP改造
问题描述 LG2375 LOJ2246 题解 看了题解,需要回看,需要继续通过本题深入理解KMP. 为了将 \(\mathrm{KMP}\) 和只插入了一个模式串的\(\mathrm{AC}\)自动机 ...
随机推荐
- sparse coding
Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...
- [转]程序进行性能分析工具gprof使用入门
性能分析工具 软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键.这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是 ...
- 【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介
Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区 ...
- github 优秀的开源项目
https://github.com/wlcaption/AndroidMarket---- 这是手机应用商店,包含应用的下载,用户中心等内容 https://github.com/wlcaption ...
- 数据库-mysql视图
视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用 一:创建视图 create view view ...
- spotlight on mysql--安装以及简介
Spotlight on MySQL 安装与配置 第一步: 下载并安装mysql-connector-3.5x Spotlight on MySQL 连接mysql必须使用mysql-connecto ...
- KVM和远程管理工具virt-manager
kvm在server端的部署(针对rhel6系统,可以构建本地更新源) 注意:如果只是安装管理工具,可以试试直接执行8步骤 1.对服务器实行kvm虚拟化首先需要确认服务器的物理硬件是否支持 cat / ...
- Java--Jackson转换Date,Timestamp 到格式化字符串
package com.diandaxia.test; import java.sql.Timestamp; import java.util.Date; /** * Created by del-b ...
- Linux下LAMP服务器的搭建
1.安装并配置Apache 安装apache的方法有很多种,这里选择通过yum方式进行安装,但需要Linux系统能够连接互联网,执行如下命令,安装Apache. # yum install httpd ...
- 网络编程--Socket与ServerSocket
1.服务器端代码 package net; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Sock ...