「NOI2014」购票

解题思路

先列出 \(dp\) 式子并稍微转化一下

\[dp[u] =\min(dp[v]+(dis[u]-dis[v]) \times p[u] + q[u])) \ \ \ \ (dis[v]-lim[u] \leq dis[u]) \\
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\) 优,可以得到斜率式

\[dp(v2)+p(u)\times dis(v2)\leq dis(v1)+p(u)\times dp(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」购票的更多相关文章

  1. 「NOI2014」购票 解题报告

    「NOI2014」购票 写完了后发现写的做法是假的...然后居然过了,然后就懒得管正解了. 发现需要维护凸包,动态加点,询问区间,强制在线 可以二进制分组搞,然后你发现在树上需要资瓷撤回,然后暴力撤回 ...

  2. LOJ#2249 Luogu P2305「NOI2014」购票

    几乎肝了半个下午和整个晚上 斜率优化的模型好多啊... LOJ #2249 Luogu P2305 题意 给定一棵树,第$ i$个点如果离某个祖先$ x$的距离不超过$ L_i$,可以花费$ P_i· ...

  3. LOJ 2249: 洛谷 P2305: 「NOI2014」购票

    题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...

  4. LOJ 2249: 洛谷 P2305: bzoj 3672: 「NOI2014」购票

    题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...

  5. 【LOJ】#2244. 「NOI2014」起床困难综合症

    题解 写水题放松一下心情 二进制有个很好的性质是每一位是独立的,我们按位贪心,先看这一位能不能填1,然后看看如果这一位填0那么运算后最后这一位是不是1,是的话就退出,然后看看这一位如果填1最后是1这一 ...

  6. 「NOI2014」魔法森林

    题目链接 戳我 \(Solution\) 两个变量,emm...不好搞啊. 于是我们可以按照\(A\)排序.然后动态加边,因为\(A\)是越来越大,所以不需要管他,只要使得\(1\)~\(n\)的路径 ...

  7. LOJ#2244. 「NOI2014」起床困难综合症

    $n \leq 1e5$个位运算操作,$m \le 2^{30}$,问$0-m$中谁进行完所有操作值最大,输出这个最大值. cfA题难度?当送分题就不管了 and相当于几个位取0,or相当于几个位取1 ...

  8. 「NOI2014」动物园

    link : https://loj.ac/problem/2246 水水KMP #include<bits/stdc++.h> #define ll long long #define ...

  9. LG2375/LOJ2246 「NOI2014」动物园 KMP改造

    问题描述 LG2375 LOJ2246 题解 看了题解,需要回看,需要继续通过本题深入理解KMP. 为了将 \(\mathrm{KMP}\) 和只插入了一个模式串的\(\mathrm{AC}\)自动机 ...

随机推荐

  1. transparent 透明效果

    background-color:transparent;就是把背景色设置为透明. 实际上background默认的颜色就是透明的属性.所以写和不写都是一样的 span{ width: 0; heig ...

  2. ECMAScript——(二)

    1.语法 区分大小写 变量是弱类型(定义变量时只用 var 运算符,可以将它初始化为任意值.) 每行结尾的分号可有可无(建议写上) 注释与Java一样 括号表示代码块 2.变量 变量可以不用声明,变量 ...

  3. perl6 HTTP::UserAgent发送post

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; say 'All method:'; say $ua.^methods; my %data = : ...

  4. imperva 网管替换

    事情是这样的 某某银行的imperva DAM审计设备出现蜂鸣的响声.经检查电源没有问题,怀疑是硬盘坏了 . 然后我就去底层查看 运行命令 :impctl platform storage raid ...

  5. 83.Linux之ubuntu-14.04.4-desktop-amd64安装

    QQ(1044233591) 一.软件下载 二.安装 1.上一节已经安装好了VMware10.0.4软件,双击桌面VMware Workstation软件图标,出现VMware软件界面,点击" ...

  6. Linux下编译安装qemu和libvirt【转】

    转自:http://www.cnblogs.com/findumars/p/5679742.html 目录 [hide] 1 安装qemu 1.1 qemu介绍 1.2 下载源文件 1.3 编译安装 ...

  7. Git log diff config高级进阶

    Git 历史相关和 git config 高级进阶 前一段时间分享了一篇<更好的 git log>简要介绍怎么美化 git log 命令,其中提到了 alias命令,今天再继续谈谈 git ...

  8. 03 Go 1.3 Release Notes

    Go 1.3 Release Notes Introduction to Go 1.3 Changes to the supported operating systems and architect ...

  9. Session和Cookie,Django的自动登录机制

    什么是Cookie? Cookie是浏览器的本地存储机制,存储服务器返回的各种信息,下次发起请求时再发送给服务端,比如访问baidu 什么是Session? 刚才说道,Cookie存储服务端返回的信息 ...

  10. js数据绑定(模板引擎原理)

    <div> <ul id="list"> <li>11111111111</li> <li>22222222222< ...