「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}\)自动机 ...
随机推荐
- hdu 1251 统计难题(字典树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251 统计难题 Time Limit: 4000/2000 MS (Java/Others) M ...
- VUE项目用hbuilder 打包为手机APP
一.测试项目是否可以正确运行 指令:npm run dev 首先我们先建立一个vue的项目,本人用的是vue-cli随便建立的,然后运行项目 不必非得是像我这样的,这一步的目的只是测试一下咱们的 ...
- [转]std::set、自定义类型与比较函数
转自:http://www.189works.com/article-42025-1.html 怎样在set中放入自定义类型?这个问题通过谷歌就可以得到不少答案:1.定义一个函数对象并在定义set的时 ...
- java连接redis无法连接,报异常RedisConnectionException
不管是spring还是原生jedis连接redis,如果连不上多半是linux服务器的问题: 1 首先确保redis端口开放: 把6379或者redis的端口开放即可 2 redis.conf配置注释 ...
- aarch64_m2
mingw32-leptonica-1.74.4-1.fc26.noarch.rpm 2017-06-12 17:20 1.0M fedora Mirroring Project mingw32-le ...
- jQuery-对标签元素 文本操作-属性操作-文档的操作
一.对标签元素文本操作 1.1 对标签中内容的操作 // js var div1 = document.getElementById("div1"); div1.innerText ...
- 04 Effective Go 高效的go语言 重点内容
Effective Go 高效的go语言 Introduction 介绍 Examples 例子 Formatting 格式 Commentary 评论 Names 名字 Package names ...
- MySQL权限操作:Grant、Revoke
数据库操作: 创建数据库.创建表——CREATE 删除数据库.删除表——DROP 删除表内容——TRUNCATE.DELETE(后者效率低.一行一行地删除记录) 查询数据库.查询表——SELECT 插 ...
- Mysql Limit操作
oracle : || mysql: contact contact_ws 拼接 Font Size: Large | Medium | Small select * from tabl ...
- java基础80 JSP基础知识点(网页知识)
1.jsp的引入 Servlet的作用:用java语言开发动态资源技术!!! Jsp的作用:用java语言(+html语言)开发的动态资源技术!!! Jsp就是servlet 问题:为什 ...