【NOI2014】购票 线段树做法
2015-11-09 15:48
267 查看
先推出动态转移方程方程,它有一个距离限制,这一维可以用线段树维护,然后线段树中的凸包要求有回溯操作,这个每次只会修改top和那一为的值,记录一下即可。(bzoj上TLE了。。。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #define Rep(i, x, y) for (int i = x; i <= y; i ++) #define Dwn(i, x, y) for (int i = x; i >= y; i --) #define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex) #define pb push_back #define u t[x] #define Lc t[x + x] #define Rc t[x + x + 1] using namespace std; typedef long long LL; typedef long double DB; const int N = 200005; const LL inf = 1LL << 62; struct Edge { LL x, y, nex; } g , g2[N*30], gx[N*30]; struct Seg_node { vector<LL> qx, qy; int tl; LL lx, rx; } t[N*8]; int n, T0, pos , sz, sz2, p1[N*4], szx, p0[N*4], fa ; LL qx, qy, lz , a , b , l , lt , f , q, h ; void Init(int x, int y) { g[++ sz] = (Edge) { 0, y, pos[x] }, pos[x] = sz; } void Add1(int x, LL y) { g2[++ sz2] = (Edge) { y, 0, p1[x] }, p1[x] = sz2; } void Add2(int x, LL y, LL z) { gx[++ szx] = (Edge) { y, z, p0[x] }, p0[x] = szx; } LL Qry(int x, int l, int r) { if (q > u.rx || !u.tl) return inf; if (q <= u.lx) { int l = 0, r = u.tl - 1; while (l < r) { int mid = (l + r + 1) >> 1; LL x1 = (-u.qx[mid] * b[qx]) + u.qy[mid], x2 = (-u.qx[mid - 1] * b[qx]) + u.qy[mid - 1]; if (x1 < x2) l = mid; else r = mid - 1; } return (-u.qx[l] * b[qx]) + u.qy[l]; } int mid = l + r >> 1; return min(Qry(x + x, l, mid), Qry(x + x + 1, mid + 1, r)); } bool cmp(LL x1, LL y1, LL x2, LL y2, LL x3, LL y3) { return (y1 - y2) / DB(x1 - x2) <= (y2 - y3) / DB(x2 - x3); } void Upd(int x) { u.lx = min(Lc.lx, Rc.lx), u.rx = max(Lc.rx, Rc.rx); } void Ins(int x, int l, int r) { int siz = u.qx.size(), tl = u.tl; while (tl > 1 && cmp(qx, qy, u.qx[tl - 1], u.qy[tl - 1], u.qx[tl - 2], u.qy[tl - 2])) tl --; Add1(x, u.tl); if (siz == tl) u.qx.pb(qx), u.qy.pb(qy), Add2(x, 0, 0); else { Add2(x, u.qx[tl], u.qy[tl]); u.qx[tl] = qx, u.qy[tl] = qy; } u.tl = tl + 1; if (l == r) { u.lx = u.rx = qx; return ; } int mid = l + r >> 1; if (q <= mid) Ins(x + x, l, mid); else Ins(x + x + 1, mid + 1, r); Upd(x); } void Era(int x, int l, int r) { u.qx[ u.tl - 1 ] = gx[ p0[x] ].x, u.qy[ u.tl - 1 ] = gx[ p0[x] ].y, u.tl = g2[ p1[x] ].x; p0[x] = gx[ p0[x] ].nex, p1[x] = g2[ p1[x] ].nex; if (l == r) { u.lx = u.rx = 0; return ; } int mid = l + r >> 1; if (q <= mid) Era(x + x, l, mid); else Era(x + x + 1, mid + 1, r); Upd(x); } void Dfs(int x) { if (x > 1) { q = lt[x] - l[x], qx = x; f[x] = Qry(1, 1, n) + lt[x] * b[x] + a[x]; } q = h[x], qx = lt[x], qy = f[x]; Ins(1, 1, n); RepE(i, x) { int y = g[i].y; h[y] = h[x] + 1; lt[y] = lt[x] + lz[y], Dfs(y); } q = h[x]; Era(1, 1, n); } int main() { scanf ("%d%d", &n, &T0); Rep(i, 2, n) { scanf ("%d%lld%lld%lld%lld", &fa[i], &lz[i], &b[i], &a[i], &l[i]); Init(fa[i], i); } h[1] = 1, Dfs(1); Rep(i, 2, n) printf("%lld\n", f[i]); return 0; }
相关文章推荐
- SqlServer中截取小数位数
- github的简单使用
- 关于zxing设置hints.put(EncodeHintType.MARGIN, 0)无明显效果的探究
- 正则表达式
- Android 原生listview item伸展收缩效果
- Service-stack.redis 使用PooledRedisClientManager 速度慢的原因之一
- Codeforces Round #330 (Div. 2)B. Pasha and Phone 容斥
- zabbix监控dell服务器脚本及方式key值
- nginx反向代理后端IIS持续报错504
- JavaScript边学边记
- 漫威超级反派大全
- Android的init过程详解(一)
- 2.UiSelector API 详细介绍
- jade学习笔记
- 每天一个linux命令--locate
- 豆瓣FM音乐播放器
- Android常用Json解析框架GSON和FastJson的使用
- 深入浅出MIPS 三 MIPS的协处理器CP0 (Section 3)
- KVO实现原理
- 我对管理和领导的理解