BZOJ3999 [TJOI2015]旅游
题面:给定一个有$n$个节点的树,每个点又点权$v_i$,每次选取一条树链$[a, b]$,求出$max(v_i - v_j)$,其中$i, j \in [a, b]$且$i$出现在$j$前面,最后树链$[a, b]$上的点点权都加上$v'$
裸的树链剖分,用线段树维护树链。。。查询的时候要用线段树合并。。。然后就没有然后了。。。
代码能力捉鸡QAQQQ,而且貌似是C++程序里面跑的最慢的QAQQQ
/**************************************************************
Problem: 3999
User: rausen
Language: C++
Result: Accepted
Time:4268 ms
Memory:17988 kb
****************************************************************/ #include <cstdio>
#include <algorithm> using namespace std;
typedef long long ll;
const int N = 5e4 + ;
const int inf = 1e9; inline int read(); int n;
int a[N], seq[N], cnt_seq; struct edge {
int next, to;
edge() {}
edge(int _n, int _t) : next(_n), to(_t) {}
} e[N << ]; int first[N], tot; struct tree_node {
int sz, dep, fa, son, v;
int top, pos;
} tr[N]; struct seg {
seg *ls, *rs, *res;
ll mx, mn, mxl, mxr, tag; #define Len (1 << 16)
inline void* operator new(size_t) {
static seg *mempool, *c;
if (mempool == c)
mempool = (c = new seg[Len]) + Len;
return c++;
}
#undef Len
inline seg& operator += (int x) {
mx += x, mn += x, tag += x;
} inline seg* rev() {
swap(mxl, mxr);
return this;
}
inline void update(seg *ls, seg *rs) {
mxl = max(max(ls -> mxl, rs -> mxl), ls -> mx - rs -> mn);
mxr = max(max(ls -> mxr, rs -> mxr), rs -> mx - ls -> mn);
mx = max(ls -> mx, rs -> mx), mn = min(ls -> mn, rs -> mn);
}
inline void push() {
if (tag) {
*ls += tag, *rs += tag;
tag = ;
}
} #define mid (l + r >> 1)
inline void build(int l, int r, int* a) {
res = new()seg;
if (l == r) {
mx = mn = a[l];
return;
}
ls = new()seg(), rs = new()seg;
ls -> build(l, mid, a), rs -> build(mid + , r, a);
update(ls, rs);
} inline void add(int l, int r, int L, int R, int d) {
if (L <= l && r <= R) {
*this += d;
return;
}
push();
if (L <= mid) ls -> add(l, mid, L, R, d);
if (mid < R) rs -> add(mid + , r, L, R, d);
update(ls, rs);
} inline seg* query(int l, int r, int L, int R) {
if (L <= l && r <= R) {
*res = *this;
return res;
}
*res = seg(), push();
if (mid >= R) res = ls -> query(l, mid, L, R);
else if (mid < L) res = rs -> query(mid + , r, L, R);
else res -> update(ls -> query(l, mid, L, R), rs -> query(mid + , r, L, R));
update(ls, rs);
return res;
}
#undef mid
} *T; inline void get(seg *t, int f, int a, int b, int v) {
if (!f) t -> update(T -> query(, n, a, b), t);
else t -> update(t, T -> query(, n, a, b) -> rev());
T -> add(, n, a, b, v);
} inline void pre(seg *t) {
*t = seg();
t -> mx = t -> mxl = t -> mxr = -inf, t -> mn = inf;
} inline void work(int x, int y, int v) {
static seg *left = new()seg, *right = new()seg, *ans = new()seg;
pre(left), pre(right);
while (tr[x].top != tr[y].top) {
if (tr[tr[x].top].dep > tr[tr[y].top].dep)
get(right, , tr[tr[x].top].pos, tr[x].pos, v), x = tr[tr[x].top].fa;
else
get(left, , tr[tr[y].top].pos, tr[y].pos, v), y = tr[tr[y].top].fa;
}
if (tr[x].dep > tr[y].dep) get(right, , tr[y].pos, tr[x].pos, v);
else get(left, , tr[x].pos, tr[y].pos, v);
ans -> update(left, right);
printf("%lld\n", max(ans -> mxl, 0ll));
} inline void Add_Edges(int x, int y) {
e[++tot] = edge(first[x], y), first[x] = tot;
e[++tot] = edge(first[y], x), first[y] = tot;
} #define y e[x].to
void dfs(int p) {
int x;
tr[p].sz = ;
for (x = first[p]; x; x = e[x].next)
if (y != tr[p].fa) {
tr[y].fa = p, tr[y].dep = tr[p].dep + ;
dfs(y);
tr[p].sz += tr[y].sz;
if (!tr[p].son || tr[tr[p].son].sz < tr[y].sz) tr[p].son = y;
}
} void DFS(int p) {
int x;
seq[tr[p].pos = ++cnt_seq] = tr[p].v;
if (!tr[p].son) return;
tr[tr[p].son].top = tr[p].top;
DFS(tr[p].son);
for (x = first[p]; x; x = e[x].next)
if (y != tr[p].fa && y != tr[p].son)
tr[y].top = y, DFS(y);
}
#undef y int main() {
int i, x, y, z, Q;
n = read();
for (i = ; i <= n; ++i) tr[i].v = read();
for (i = ; i < n; ++i)
Add_Edges(read(), read());
dfs();
tr[].top = , DFS();
T = new()seg;
T -> build(, n, seq);
for (Q = read(); Q; --Q) {
x = read(), y = read(), z = read();
work(x, y, z);
}
return ;
} inline int read() {
static int x;
static char ch;
x = , ch = getchar();
while (ch < '' || '' < ch)
ch = getchar();
while ('' <= ch && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x;
}
BZOJ3999 [TJOI2015]旅游的更多相关文章
- BZOJ3999:[TJOI2015]旅游(树链剖分)
Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...
- BZOJ3999 [TJOI2015]旅游 【树剖 + 线段树】
题目 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会选择从A城市买入再 ...
- 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)
传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...
- 【BZOJ3999】[TJOI2015]旅游(Link-Cut Tree)
[BZOJ3999][TJOI2015]旅游(Link-Cut Tree) 题面 BZOJ 洛谷 题解 一道不难的\(LCT\)题(用树链剖分不是为难自己吗,这种有方向的东西用\(LCT\)不是方便那 ...
- bzoj 3999: [TJOI2015]旅游
Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...
- [TJOI2015]旅游
树链剖分+线段树 线段树维护max,min,左往右的最大差,右往左的最大差 求LCA时一定要注意方向 # include <bits/stdc++.h> # define RG regis ...
- P3976 [TJOI2015]旅游(未完成)
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #inc ...
- bzoj 3999: [TJOI2015]旅游 LCT
没啥难的,inf 的值设小了调了半天~ code: #include <bits/stdc++.h> #define N 50003 #define lson t[x].ch[0] #de ...
- [暑假的bzoj刷水记录]
(这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊 堆一起算了 隔一段更新一下. 7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...
随机推荐
- (linux) 常用命令 干货
内容提要 1. 第一难度, 重要 梯队 (grep, awk, sed, find, ) 2. 第二常用, 重要 梯队 (ps, ls, date, fuser, netstat, kill) 3. ...
- bootstrap学习笔记<十一>(导航条)
基础导航条.样式:class="navbar navbar-default",属性:role="navigation" <div class=" ...
- Python学习笔记13—错误和异常
常见的异常:
- 动态替换fragment
// [1]获取手机的宽和高 windommanager WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); in ...
- Android最佳性能实践(一)——合理管理内存
有不少朋友都问过我,怎样才能写出高性能的应用程序,如何避免程序出现OOM,或者当程序内存占用过高的时候该怎么样去排查.确实,一个优秀的应用程序,不仅仅要功能完成得好,性能问题也应该处理得恰到好处.为此 ...
- MFC编程入门之前言
本系列主要偏重于理论方面的知识,目的是打好底子,练好内功,在使用VC++编程时不至于丈二和尚摸不着头脑.本系列也会涉及到VC++的原理性的东西,同样更重视实用性,学完本系列以后,基本的界面程序都能很容 ...
- [转]C++中引用(&)的用法和应用实例
from: here 对于习惯使用C进行开发的朋友们,在看到c++中出现的&符号,可能会犯迷糊,因为在C语言中这个符号表示了取地址符,但是在C++中它却有着不同的用途,掌握C++的&符 ...
- Microsoft VS 2008 过期解决方法
开始>控制面板>添加或删除程序 里找到VS2008,点“更改/删除”,出现: 然后,打开“显示Visual Studio试用版序列号输入框小程序”的软件(单击链接可以转到下载地址),显示: ...
- 转!JNDI 是什么?
JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有 ...
- Intellij IDEA-can't use subversion command line client : svn
http://www.myexception.cn/cvs-svn/1935962.html