题目

为了提高智商,ZJY准备去往一个新世界去旅游。这个世界的城市布局像一棵树。每两座城市之间只有一条路径可

以互达。每座城市都有一种宝石,有一定的价格。ZJY为了赚取最高利益,她会选择从A城市买入再转手卖到B城市

。由于ZJY买宝石时经常卖萌,因而凡是ZJY路过的城市,这座城市的宝石价格会上涨。让我们来算算ZJY旅游完之

后能够赚取的最大利润。(如a城市宝石价格为v,则ZJY出售价格也为v)

输入格式

第一行输入一个正整数N,表示城市个数。

接下来一行输入N个正整数表示每座城市宝石的最初价格p,每个宝石的初始价格不超过100。

第三行开始连续输入N-1行,每行有两个数字x和y。表示x城市和y城市有一条路径。城市编号从1开始。

下一行输入一个整数Q,表示询问次数。

接下来Q行,每行输入三个正整数a,b,v,表示ZJY从a旅游到b,城市宝石上涨v。

1≤ N≤50000, 1≤Q ≤50000

输出格式

对于每次询问,输出ZJY可能获得的最大利润,如果亏本则输出0。

输入样例

3

1 2 3

1 2

2 3

2

1 2 100

1 3 100

输出样例

1

1

题解

题意是树上可修改的两点间有序差值最大值

如果是序列上的话一个线段树维护左右区间最值和答案就可以分类讨论跨不跨过中点得出各个点的答案从而做到维护答案了

如果是树上的话,考虑树剖,将路径拆成了几段几段

答案要么在一段内,要么最值分别分布在两段内

我们就用每一段的答案更新答案,再单独拿出所有的\(O(logn)\)段,考虑相互影响来更新答案

细节上要注意树上路径的方向

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 50005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 2;
struct EDGE{int to,nxt;}ed[maxn << 1];
inline void Build(int u,int v){
ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v]}; h[v] = ne++;
}
int n,A[maxn];
int fa[maxn],siz[maxn],son[maxn],top[maxn],dep[maxn],id[maxn],hash[maxn],cnt;
void dfs1(int u){
siz[u] = 1;
Redge(u) if ((to = ed[k].to) != fa[u]){
fa[to] = u; dep[to] = dep[u] + 1;
dfs1(to);
siz[u] += siz[to];
if (!son[u] || siz[son[u]] < siz[to]) son[u] = to;
}
}
void dfs2(int u,int flag){
id[u] = ++cnt; hash[cnt] = u;
top[u] = flag ? top[fa[u]] : u;
if (son[u]) dfs2(son[u],true);
Redge(u) if ((to = ed[k].to) != fa[u] && to != son[u])
dfs2(to,false);
}
int mx[maxn << 2],mn[maxn << 2],d1[maxn << 2],d2[maxn << 2],tag[maxn << 2];
void upd(int u){
mx[u] = max(mx[ls],mx[rs]);
mn[u] = min(mn[ls],mn[rs]);
d1[u] = max(max(d1[ls],d1[rs]),mx[rs] - mn[ls]);
d2[u] = max(max(d2[ls],d2[rs]),mx[ls] - mn[rs]);
}
void pd(int u){
if (tag[u]){
mx[ls] += tag[u]; mn[ls] += tag[u]; tag[ls] += tag[u];
mx[rs] += tag[u]; mn[rs] += tag[u]; tag[rs] += tag[u];
tag[u] = 0;
}
}
void build(int u,int l,int r){
if (l == r){
mx[u] = mn[u] = A[hash[l]];
return;
}
int mid = l + r >> 1;
build(ls,l,mid);
build(rs,mid + 1,r);
upd(u);
}
void add(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R){
mx[u] += v; mn[u] += v; tag[u] += v;
return;
}
pd(u);
int mid = l + r >> 1;
if (mid >= L) add(ls,l,mid,L,R,v);
if (mid < R) add(rs,mid + 1,r,L,R,v);
upd(u);
}
struct node{int mx,mn,d1,d2;};
node query(int u,int l,int r,int L,int R){
if (l >= L && r <= R) return (node){mx[u],mn[u],d1[u],d2[u]};
pd(u);
int mid = l + r >> 1;
if (mid >= R) return query(ls,l,mid,L,R);
if (mid < L) return query(rs,mid + 1,r,L,R);
node t1 = query(ls,l,mid,L,R),t2 = query(rs,mid + 1,r,L,R);
return (node){max(t1.mx,t2.mx),min(t1.mn,t2.mn),max(max(t1.d1,t2.d1),t2.mx - t1.mn),max(max(t1.d2,t2.d2),t1.mx - t2.mn)};
}
node st[2][100],e[100];
int Top[2],tot;
void solve(int u,int v,int w){
int p = 0,ans = 0; Top[0] = Top[1] = 0;
while (top[u] != top[v]){
if (dep[top[u]] < dep[top[v]]){
swap(u,v);
p ^= 1;
}
add(1,1,n,id[top[u]],id[u],w);
st[p][++Top[p]] = query(1,1,n,id[top[u]],id[u]);
u = fa[top[u]];
}
p ^= 1;
if (dep[u] > dep[v]){
swap(u,v);
p ^= 1;
}
add(1,1,n,id[u],id[v],w);
st[p][++Top[p]] = query(1,1,n,id[u],id[v]);
tot = 0;
for (int i = 1; i <= Top[0]; i++){
e[++tot] = st[0][i];
ans = max(ans,e[tot].d2);
}
for (int i = Top[1]; i; i--){
e[++tot] = st[1][i];
ans = max(ans,e[tot].d1);
}
int gmin = INF;
for (int i = 1; i <= tot; i++){
ans = max(ans,e[i].mx - gmin);
gmin = min(gmin,e[i].mn);
}
printf("%d\n",ans);
}
int main(){
n = read();
REP(i,n) A[i] = read();
for (int i = 1; i < n; i++) Build(read(),read());
dfs1(1);
dfs2(1,0);
build(1,1,n);
int m = read(),a,b,w;
while (m--){
a = read(); b = read(); w = read();
solve(a,b,w);
}
return 0;
}

BZOJ3999 [TJOI2015]旅游 【树剖 + 线段树】的更多相关文章

  1. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  2. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  3. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  4. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  5. [LNOI2014]LCA(树剖+线段树)

    \(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...

  6. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  7. LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)

    题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...

  8. BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)

    传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...

  9. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  10. POJ3237 Tree(树剖+线段树+lazy标记)

    You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...

随机推荐

  1. Count Numbers(矩阵快速幂)

    Count Numbers 时间限制: 8 Sec  内存限制: 128 MB提交: 43  解决: 19[提交] [状态] [讨论版] [命题人:admin] 题目描述 Now Alice want ...

  2. SpringBoot学习记录(二)

    一. SpringBoot日志框架 SpringBoot:底层是Spring框架,Spring框架默认是用JCL(commons-logging): SpringBoot选用SLF4j和logback ...

  3. 魅族MX3 Flyme3.0找回手机功能支持远程拍照密码错两次自动拍照

    进入Flyme页面(http://app.meizu.com/),选择“查找手机”即可进行查找自己登记的魅族系列手机. 如果您在一个账号下登记过N多魅族系列手机,那么都是可以进行查找的,参见下图 魅族 ...

  4. AngularJS 对象

    AngularJS对象就像JavaScript对象 <!DOCTYPE html><html><head><meta http-equiv="Con ...

  5. z-index、absolute、marquee滚动条的问题

    1.z-index 层次叠加 ,元素叠加,谁的权重大谁就在上面 1).父级出现position:relation:的时候,失效: 2).层叠元素出现float的时候失效: 3).层次元素也得设置pos ...

  6. 洛谷P1048采药

    这道题一看就知道是01背包,我门用f[i]来表示时间剩余i时的最大的价值 一共只有两种选择取或者不取,可以得到方程式f[i]=max(f[i],f[i-a[i]]+v[i])(a[i]是表示时间,v[ ...

  7. PowerDesigner导入Excel模板生成实体

        在Excel里整理好的表模型数据,可直接导入PowerDesigner.此功能通过PowerDesigner的脚本功能来实现,使用起来也简单.具体操作方法:     打开PowerDesign ...

  8. vue.js 发布后路径引用问题

    在发布到iis目录下时候,如果放在网站的根目录下的时候,是不会有什么问题的 但是一旦放在了非根目录的其他文件夹里面,这时候index.html里引用的js和css文件路径都会找不到 错误如下 打开in ...

  9. js中如何把RGB颜色转换为16进制颜色

    将RGB颜色值转换为16进制颜色值,主要是将 R.G.B 值分别转换为对应的十六进制值,填入 #RRGGBB 中. 推荐在线颜色转换工具:http://www.ecjson.com/rgbhex/ 例 ...

  10. 服务端Latex解析成图片或者HTML或者SVG方案

    Latex公式表达式在服务端进行转换成可用数据 使用语言与扩展 node.js Mathjax (文档链接) MathJax在nodejs上解决方案 mathjax/MathJax-node(GitH ...