3999: [TJOI2015]旅游

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 423  Solved: 214
[Submit][Status][Discuss]

Description

为了提高智商,ZJY准备去往一个新世界去旅游。这个世界的城市布局像一棵树。每两座城市之间只有一条路径可
以互达。每座城市都有一种宝石,有一定的价格。ZJY为了赚取最高利益,她会选择从A城市买入再转手卖到B城市
。由于ZJY买宝石时经常卖萌,因而凡是ZJY路过的城市,这座城市的宝石价格会上涨。让我们来算算ZJY旅游完之
后能够赚取的最大利润。(如a城市宝石价格为v,则ZJY出售价格也为v)

Input

第一行输入一个正整数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

Output

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

Sample Input

3
1 2 3
1 2
2 3
2
1 2 100
1 3 100

Sample Output

1
1

HINT

Source

[Submit][Status][Discuss]

题解:树链剖分。

我们要使区间中,后面-前面的差值最大,那么考虑一个问题那些数可能对答案产生贡献。应该有两种方式,一种是选取最小值,然后再在最小值所在的位置后面选取一个最大的数,两个的差可能是答案;还有一种是选取最大值,然后再在最大值所在位置的前面选取一个最小值,两个做差。也就是说我们需要按旅行的顺序提取链剖上的区间,然后一次计算差值更新答案。

刚开始想的是用线段树维护最大值,最小值以及他们所在的位置,后来发现位置不唯一,而且从起点向上走,得到的区间应该是与旅行的顺序相反的,而从终点向上走,得到的区间正好是相同的,所以维护位置太过麻烦,于是直接维护差值。差值需要维护两个一个是后面的最大值-前面的最小值,另一个是前面的最大值-后面的最小值,这样两个根据提取的区间与旅行顺序是否一致,从中选择一个来更新答案即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 50003
#define LL long long
#define inf 1e18
using namespace std;
int n,m,point[N*2],next[N*2],v[N*2],val[N],tot,sz;
int pos[N],size[N],son[N],deep[N],fa[N],belong[N],a[N];
LL tr[N*4],tr1[N*4],posx[N*4],posn[N*4],delta[N*4];
LL xl[N],yl[N],xr[N],yr[N];
struct data
{LL maxn,minn,posx,posn;
};
void add(int x,int y)
{tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs1(int x,int f)
{fa[x]=f; size[x]=1;for (int i=point[x];i;i=next[i])if (v[i]!=f){deep[v[i]]=deep[x]+1;dfs1(v[i],x);size[x]+=size[v[i]];if (size[son[x]]<size[v[i]])son[x]=v[i];}
}
void dfs(int x,int chain)
{pos[x]=++sz; a[sz]=val[x]; belong[x]=chain;if (!son[x]) return;dfs(son[x],chain);for (int i=point[x];i;i=next[i])if (v[i]!=fa[x]&&v[i]!=son[x])dfs(v[i],v[i]);
}
void update(int now)
{tr[now]=max(tr[now<<1],tr[now<<1|1]);tr1[now]=min(tr1[now<<1],tr1[now<<1|1]);posx[now]=max(posx[now<<1],posx[now<<1|1]);posx[now]=max(posx[now],tr[now<<1|1]-tr1[now<<1]);posn[now]=max(posn[now<<1],posn[now<<1|1]);posn[now]=max(posn[now],tr[now<<1]-tr1[now<<1|1]);
}
void build(int now,int l,int r)
{if (l==r){tr[now]=tr1[now]=(LL)a[l];posx[now]=posn[now]=0;return;}int mid=(l+r)/2;build(now<<1,l,mid);build(now<<1|1,mid+1,r);update(now);//cout<<l<<" "<<r<<" "<<posx[now]<<" "<<posn[now]<<endl;
}
void pushdown(int now)
{if (delta[now]){tr[now<<1]+=delta[now]; tr[now<<1|1]+=delta[now];tr1[now<<1]+=delta[now]; tr1[now<<1|1]+=delta[now];delta[now<<1]+=delta[now]; delta[now<<1|1]+=delta[now];delta[now]=0;}
}
void change(int now,int l,int r,int ll,int rr,LL v)
{if (ll<=l&&r<=rr){tr[now]+=v;tr1[now]+=v;delta[now]+=v;return;}int mid=(l+r)/2;pushdown(now);if (ll<=mid) change(now<<1,l,mid,ll,rr,v);if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,v);update(now);
}
data ask(int now,int l,int r,int ll,int rr)
{if (ll<=l&&r<=rr){data a;a.maxn=tr[now]; a.minn=tr1[now];a.posx=posx[now]; a.posn=posn[now];return a;}int mid=(l+r)/2;pushdown(now);data a,t,t1; bool f=false,f1=false;a.maxn=0; a.minn=inf; a.posx=0; a.posn=0;t.maxn=0; t.minn=inf; t.posx=0; t.posn=0;t1.maxn=0; t1.minn=inf; t1.posx=0; t1.posn=0; if (ll<=mid)   t=ask(now<<1,l,mid,ll,rr),f=true;if (rr>mid)   t1=ask(now<<1|1,mid+1,r,ll,rr),f1=true;a.maxn=max(t.maxn,t1.maxn);a.minn=min(t.minn,t1.minn);a.posx=max(t.posx,t1.posx);if (f&&f1) a.posx=max(a.posx,t1.maxn-t.minn);a.posn=max(t.posn,t1.posn);if (f&&f1) a.posn=max(a.posn,t.maxn-t1.minn);return a;
}
void solve(int x,int y,LL z)
{while (belong[x]!=belong[y]){if (deep[belong[x]]<deep[belong[y]])  swap(x,y);change(1,1,n,pos[belong[x]],pos[x],z);x=fa[belong[x]];}if (deep[x]>deep[y]) swap(x,y);change(1,1,n,pos[x],pos[y],z);
}
LL solve1(int x,int y)
{int cnt=0,cnt1=0; LL ans=0;while (belong[x]!=belong[y]){if (deep[belong[x]]>deep[belong[y]]){data t=ask(1,1,n,pos[belong[x]],pos[x]);ans=max(ans,t.posn);xl[++cnt]=t.minn; xr[cnt]=t.maxn;x=fa[belong[x]];}else {data t=ask(1,1,n,pos[belong[y]],pos[y]);ans=max(ans,t.posx);yl[++cnt1]=t.minn; yr[cnt1]=t.maxn;y=fa[belong[y]];}}if (deep[x]>deep[y]) {swap(x,y);data t=ask(1,1,n,pos[x],pos[y]);ans=max(ans,t.posn);xl[++cnt]=t.minn; xr[cnt]=t.maxn;}else{data t=ask(1,1,n,pos[x],pos[y]);ans=max(ans,t.posx);yl[++cnt1]=t.minn; yr[cnt1]=t.maxn;}for (int i=cnt1;i>=1;i--)xl[++cnt]=yl[i],xr[cnt]=yr[i];LL minn=inf;for (int i=1;i<=cnt;i++){ans=max(ans,xr[i]-minn);minn=min(minn,xl[i]);}LL maxn=0;for (int i=cnt;i>=1;i--){ans=max(ans,maxn-xl[i]);maxn=max(maxn,xr[i]);}return ans;
}
int main()
{freopen("a.in","r",stdin);freopen("my.out","w",stdout);scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&val[i]);for (int i=1;i<n;i++){int x,y; scanf("%d%d",&x,&y);add(x,y);}dfs1(1,0); dfs(1,1);build(1,1,n);scanf("%d",&m);for (int i=1;i<=m;i++){int x,y; LL z; scanf("%d%d%I64d",&x,&y,&z);printf("%I64d\n",solve1(x,y));solve(x,y,z);}
}

bzoj 3999: [TJOI2015]旅游(树链剖分)相关推荐

  1. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  2. P1505 [国家集训队]旅游 树链剖分

    题目链接 题意:树上更新某一点权值,更新两点简单路径权值,查询最大,最小,和 思路:思路应该比较简单,就是树链剖分后用线段树维护区间最大最小以及区间和. 但是本题比较特殊的是给的边权,转化为点权即可. ...

  3. BZOJ 4034 [HAOI2015]T2 树链剖分

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  4. BZOJ 4034: [HAOI2015]T2 树链剖分

    4034: [HAOI2015]T2 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操 ...

  5. bzoj 4127: Abs(树链剖分+线段树)

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 667  Solved: 225 [Submit][Status][Discuss ...

  6. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

  7. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  8. BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)

    毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...

  9. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

最新文章

  1. python能不能连等赋值_javascript 连等赋值问题
  2. angular.js前端和后台的数据交换,后台取不到值对应方案
  3. HALCON示例程序sequence_diff.hdev通过两张连续图像进行车辆流量监控
  4. 福州3 2五年制计算机专业的学校,福州有哪些五年制大专
  5. android+残留软件包名,关于使用pm hide伪卸载系统软件的一些包名
  6. 从零开始学Pytorch(三)之多层感知机的实现
  7. apk 反编译工具的使用
  8. JSP提交中文乱码的解决
  9. linux的FTP服务器搭建及FTP服务器的入侵和防御
  10. python urlopen_Python爬虫教程-02-使用urlopen
  11. HDFView 把 JPG 图片转换成 HDF5 格式文件
  12. 【计算机网络学习笔记04】网络体系架构与网络协议
  13. 读《看见》第一章观后有感
  14. 支持小游戏开发的“引擎四剑客”
  15. javaweb表格制作举例
  16. Java获取本月有多少天
  17. 拼写检查工具是android,Android拼写检查器
  18. 在世界读书日之后,重温与好书相遇的时光 | O'Reilly赠书活动
  19. MPC系列:Beaver三元组和BMR协议
  20. CPU中寄存器作用及说明

热门文章

  1. BUAA 编译作业 练习2-1 2-2 2-3
  2. Java代码操作win后台进程
  3. 《职业形象与商务礼仪》
  4. 少年启示录系列之---【人生到底怎样过?】
  5. commvault 配置mysql_Commvault_Oracle DG恢复到单机操作手册
  6. [VB程序设计创新实验教程]Chap1---VB中游戏基本要素的实现方式[1]
  7. ←机器人工程或机器人方向毕业设计汇总篇→↓2022↑
  8. 疫情专供8个网站,可攻可守不破防,让你工作、学习效率加倍
  9. 论计算机网络的安全性设计-1
  10. 神经网络与卷积神经网络,神经网络层数的确定