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 ...
随机推荐
- 用Hbase存储Log4j日志数据:HbaseAppender
业务需求: 需求很简单,就是把多个系统的日志数据统一存储到Hbase数据库中,方便统一查看和监控. 解决思路: 写针对Hbase存储的Log4j Appender,有一个简单的日志储存策略,把Log4 ...
- hdu 5643 King's Game 约瑟夫变形
首先约瑟夫问题的数学推理过程:我们知道第一个人(编号一定是(m-1) mod n) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m mod n的人开始):k k+1 k+2 ... ...
- 关于Ubuntu中passwd、shadow、group等文件
在Ubuntu系统中,/etc目录下,有三个文件:passwd shadow group,可能我们已经在用了,但是没有注意到其详细. 这三个配置文件用于系统帐号管理,都是文本文件,可用vi等文本编辑器 ...
- shiro连接数据库
建一个jdbcRealm.ini [main] jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm dataSource=com.mchange.v2.c3 ...
- jQuery Jcrop API参数说明(中文版)(转)(图片剪切)
Jcrop是一个jQuery图片裁剪插件,它能为你的WEB应用程序快速简单地提供图片裁剪的功能.特点如下: 对所有图片均unobtrusively(无侵入的,保持DOM简洁) 支持宽高比例锁定 支持 ...
- java中String的常用方法
java中String的常用方法1.length() 字符串的长度 例:char chars[]={'a','b'.'c'}; String s=new String(chars); int len= ...
- system v和posix的共享内存对比 & 共享内存位置
参考 http://www.startos.com/linux/tips/2011012822078.html 1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间. 2 ...
- windows服务名称不是单个单词的如何启动?
比如要启动 Memcached Server: 命令行中输入命令要注意大小写,大小写要保持一致,正确的写法如下: net start "Memcached Server". ...
- 【linux命令】grep
1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局 ...
- Web服务器异常问题记录
1.使用命令,出现"-bash: 命令: Input/output error" 重启服务器后正常,网上查了下是说硬盘写入读取异常,经过和服务器厂商沟通后,确认是硬件问题导致(硬盘 ...