您的位置:首页 > 其它

【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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: