Brief Description

Alice 和 Bob 在玩一个游戏。

游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。

有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,

若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。

他需要先从这条路径上选择一个点,再从那个点上选择一个数字。

Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。

Algorithm Design

良心题解

Note

写线段树的时候一定要思考使用三段式还是两段式...因为这个被卡了一天.

数据结构题一定要多出几组数据看一看.

Code

#include <algorithm>
#include <cstdio>
using namespace std;
#define ll long long
const ll inf = 123456789123456789LL;
const ll maxn = 200100;
ll ans;
ll n, m, cnt = 1;
struct edge {
ll to, next;
ll w;
} e[maxn << 1];
ll head[maxn], size[maxn], belong[maxn], vis[maxn], fa[maxn][18];
ll deep[maxn], dep[maxn];
ll pl[maxn], que[maxn], sz = 0, fu = 0;
void add_edge(ll u, ll v, ll w) {
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
void add(ll u, ll v, ll w) {
add_edge(u, v, w);
add_edge(v, u, w);
}
void dfs1(ll x) {
vis[x] = size[x] = 1;
for (ll i = 1; i <= 17; i++) {
if (dep[x] < (1 << i))
break;
fa[x][i] = fa[fa[x][i - 1]][i - 1];
}
for (ll i = head[x]; i; i = e[i].next) {
if (!vis[e[i].to]) {
deep[e[i].to] = deep[x] + e[i].w;
dep[e[i].to] = dep[x] + 1;
fa[e[i].to][0] = x;
dfs1(e[i].to);
size[x] += size[e[i].to];
}
}
}
void dfs2(ll x, ll chain) {
pl[x] = ++sz;
que[sz] = x;
belong[x] = chain;
ll k = 0;
for (ll i = head[x]; i; i = e[i].next)
if (dep[e[i].to] > dep[x] && size[k] < size[e[i].to])
k = e[i].to;
if (!k)
return;
dfs2(k, chain);
for (ll i = head[x]; i; i = e[i].next) {
if (e[i].to != k && dep[e[i].to] > dep[x])
dfs2(e[i].to, e[i].to);
}
}
struct seg {
ll l, r;
ll minn, id;
} t[maxn << 2];
struct Line {
ll k, b;
ll id;
Line(ll a = 0, ll bb = 0, ll i = 0) : k(a), b(bb), id(i) {}
inline ll getf(ll x) { return k * deep[x] + b; }
} lim[maxn << 2];
inline bool cmp(Line a, Line b, ll x) {
return a.getf(x) != b.getf(x) ? a.getf(x) < b.getf(x) : a.id < b.id;
}
void build(ll k, ll l, ll r) {
t[k].l = l, t[k].r = r, t[k].minn = inf;
if (l == r) {
return;
}
ll mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
}
void up(ll k) {
ll l = t[k].l, r = t[k].r;
if (l < r) {
t[k].minn = std::min(t[k << 1 | 1].minn, t[k << 1].minn);
} else
t[k].minn = inf;
if (t[k].id) {
t[k].minn = std::min(t[k].minn, std::min(lim[t[k].id].getf(que[l]),
lim[t[k].id].getf(que[r])));
}
}
void update(ll k, Line v) {
ll l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (t[k].id == 0) {
t[k].id = v.id;
} else {
Line tmp = lim[t[k].id];
ll x1 = v.getf(que[l]), y1 = v.getf(que[r]);
ll x2 = tmp.getf(que[l]), y2 = tmp.getf(que[r]);
if (x1 <= x2 && y1 <= y2) {
t[k].id = v.id;
} else if (x1 >= x2 && y1 >= y2)
return;
else if (v.k < tmp.k) {
ll tp = (v.b - tmp.b) / (tmp.k - v.k) + 1;
if (tp <= deep[que[mid]]) {
Line wtf = lim[t[k].id];
t[k].id = v.id;
v = wtf;
update(k << 1, v);
} else
update(k << 1 | 1, v);
} else {
ll tp = (tmp.b - v.b - 1) / (v.k - tmp.k);
if (tp > deep[que[mid]]) {
Line wtf = lim[t[k].id];
t[k].id = v.id;
v = wtf;
update(k << 1 | 1, v);
} else
update(k << 1, v);
}
}
up(k);
} void Insert(ll k, ll x, ll y, Line v) {
ll l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (x <= l && r <= y) {
update(k, v);
return;
}
if (x <= mid)
Insert(k << 1, x, y, v);
if (y > mid)
Insert(k << 1 | 1, x, y, v);
up(k);
}
void Alice(ll s, ll t, Line v) {
while (belong[s] != belong[t]) {
Insert(1, pl[belong[s]], pl[s], v);
s = fa[belong[s]][0];
}
Insert(1, pl[t], pl[s], v);
}
ll lca(ll x, ll y) {
for (; belong[x] != belong[y]; x = fa[belong[x]][0])
if (deep[belong[x]] < deep[belong[y]])
std::swap(x, y);
return (deep[x] < deep[y]) ? x : y;
}
void query(ll k, ll x, ll y) {
ll l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (x == l && r == y) {
ans = std::min(ans, t[k].minn);
return;
}
if (t[k].id)
ans = std::min(
ans, std::min(lim[t[k].id].getf(que[x]), lim[t[k].id].getf(que[y])));
if (y <= mid)
query(k << 1, x, y);
else if (x > mid)
query(k << 1 | 1, x, y);
else {
query(k << 1, x, mid);
query(k << 1 | 1, mid + 1, y);
}
}
void Bob(ll x, ll f) {
while (belong[x] != belong[f]) {
query(1, pl[belong[x]], pl[x]);
x = fa[belong[x]][0];
}
query(1, pl[f], pl[x]);
}
int main() {
freopen("menci_game.in", "r", stdin);
freopen("menci_game.out", "w", stdout);
scanf("%lld %lld", &n, &m);
for (ll i = 1; i < n; i++) {
ll u, v;
ll w;
scanf("%lld %lld %lld", &u, &v, &w);
add(u, v, w);
}
dfs1(1);
dfs2(1, 1);
build(1, 1, sz);
while (m--) {
ll opt, s, t;
scanf("%lld %lld %lld", &opt, &s, &t);
if (opt == 1) {
ll a, b;
scanf("%lld %lld", &a, &b);
fu++;
lim[fu] = Line(-a, b + a * deep[s], fu);
ll l = lca(s, t);
Alice(s, l, lim[fu]);
fu++;
lim[fu] = Line(a, lim[fu - 1].b - 2 * a * deep[l], fu);
Alice(t, l, lim[fu]);
} else {
ans = inf;
for (; belong[s] != belong[t]; s = fa[belong[s]][0]) {
if (deep[belong[s]] < deep[belong[t]])
std::swap(s, t);
query(1, pl[belong[s]], pl[s]);
}
if (deep[s] > deep[t])
std::swap(s, t);
query(1, pl[s], pl[t]);
printf("%lld\n", ans);
}
}
}

[bzoj4515][Sdoi2016]游戏-树链剖分+李超线段树的更多相关文章

  1. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

  2. bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1536  Solved: 508[Submit][Status] ...

  3. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  4. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  5. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4637  Solved: 1726[Submit][Status ...

  7. HDU 4366 Successor(树链剖分+zkw线段树+扫描线)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...

  8. 【BZOJ3531】旅行(树链剖分,线段树)

    [BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...

  9. 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)

    [BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...

随机推荐

  1. 指纹识别人脸识别 iOS

    //1.判断iOS8及以后的版本 if([UIDevice currentDevice].systemVersion.doubleValue >= 8.0){ //从iPhone5S开始,出现指 ...

  2. springmvc常用jar包

    <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans ...

  3. ant-design 实现一个登陆窗口

    前提:已经完成项目实战(https://ant.design/docs/react/practical-projects-cn#定义-Model) 如果要想实现一个登陆窗口,首先得有一个ui,想到的是 ...

  4. (原)自定义资源预览工具:DZAssetPreviewPlugin(1)

    @author: 白袍小道 转载请说明,谢谢     题记 后续工具制作单独作为一本(小道用的是OneNote,这样发布简单点.*--*) 总计放到写完后.     目的 1.快速预览资源(因为大部分 ...

  5. CentOS环境安装JDK(二)

    安装JDK-7u79-linux-x64 打开虚拟机,进入终端: 1.假设用户名是tianjiale(则需要进入管理员角色,既root) (1).将用户名tianjiale添加到sudoer列表中 提 ...

  6. cocos2d-x环境搭建 摘自百度文库

    cocos2d-x环境搭建 引言:笔者在网上寻觅了很多资料,最终发现了这份实际可用的文档,供大家参考.源地址:http://wenku.baidu.com/view/93f7b0f1102de2bd9 ...

  7. C#数据库连接问题

    最近在看C#,今天下午刚开始接触C#的数据库连接,SQL Server2008,问题如图:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名 ...

  8. idea tomcat 启动报错 org.apache.catalina.core.StandardService.initInternal Failed to initialize connector

    org.apache.catalina.core.StandardService.initInternal Failed to initialize connector org.apache.cata ...

  9. [CF15C]Industrial Nim

    题目大意:有$n$个采石场,每行一个$m_i$一个$x_i$,表示第$i$个采石场有$m_i$辆车,这个采石场中车中的石子为从$x_i$开始的自然数.Nim游戏若先手赢输出"tolik&qu ...

  10. IPVS和Nginx两种WRR负载均衡算法详解

    动机 五一临近,四月也接近尾声,五一节乃小长假的最后一天.今天是最后一天工作日,竟然感冒了,半夜里翻来覆去无法安睡,加上窗外大飞机屋里小飞机(也就是蚊子)的骚扰,实在是必须起来做点有意义的事了!    ...