BZOJ3999: [TJOI2015]旅游

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

题解Here!
额,相信大部分人肯定没有一遍读懂题意。。。
本蒟蒻也是看别的巨佬的博客弄懂的。。。
出题人语文水平真差。。。
其实就是求从$x$到$y$的有向路径上任意两个点的最大差值。

如果这只是一道线段树题还是十分简单的:
对于一个区间,其路径最大差值为:

$$\max \left( \text{右儿子最大差值,左儿子最大差值,(右儿子MAX-左儿子MIN)或者(左儿子MAX-右儿子MIN)} \right)$$

对于这样的要返回多权值的问题,线段树传递结构体比较容易。
这是链上的情况。
然后我们要求的是树的情况。
辣就用树链剖分在$O(\log_2n)$的时间内转换成链上的情况就好了嘛。。。
注意到要解决好一个方向怎么把控的问题。
因为我们在树剖一步一步一步往上爬的时候,从询问起点往上爬和询问终点往上爬是不一样的
我的处理方式是每次都进行判断是线段树左到右还是右到左扫最大差值,之后将每段区间内的$\min$和$\max$记录下来
即:分别开两个数组从起点爬的和终点爬的。
之后再将这一大段区间的$\min$和$\max$连接成一条链,直接暴力跑一次区间最大差值,得到最大答案就是了。
说得容易真的写得很恶心啊!!!

附上将近$200$行的代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define MAXSUM(x) b[x].maxn
#define MINSUM(x) b[x].minn
#define MAXL(x) b[x].maxl
#define MAXR(x) b[x].maxr
#define SIGN(x) b[x].c
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 50010
#define MAX (1LL<<62)
using namespace std;
int n,m,c=1,d=1;
int val[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],pos[MAXN],top[MAXN];
long long min_x[MAXN],max_x[MAXN],min_y[MAXN],max_y[MAXN];
struct Tree{int next,to;
}a[MAXN<<1];
struct Segment_Tree{long long maxn,minn,maxl,maxr,c;int l,r;
}b[MAXN<<2];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline long long max(const long long x,const long long y){return x>y?x:y;}
inline long long min(const long long x,const long long y){return x<y?x:y;}
inline void add(int x,int y){a[c].to=y;a[c].next=head[x];head[x]=c++;a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){son[rt]=0;size[rt]=1;for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(!deep[will]){deep[will]=deep[rt]+1;fa[will]=rt;dfs1(will);size[rt]+=size[will];if(size[son[rt]]<size[will])son[rt]=will;}}
}
void dfs2(int rt,int f){id[rt]=d++;pos[id[rt]]=rt;top[rt]=f;if(son[rt])dfs2(son[rt],f);for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);}
}
inline void pushup(int rt){MAXSUM(rt)=max(MAXSUM(LSON),MAXSUM(RSON));MINSUM(rt)=min(MINSUM(LSON),MINSUM(RSON));MAXL(rt)=max(MAXSUM(RSON)-MINSUM(LSON),max(MAXL(LSON),MAXL(RSON)));MAXR(rt)=max(MAXSUM(LSON)-MINSUM(RSON),max(MAXR(LSON),MAXR(RSON)));
}
inline void pushdown(int rt){if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;SIGN(LSON)+=SIGN(rt);MAXSUM(LSON)+=SIGN(rt);MINSUM(LSON)+=SIGN(rt);SIGN(RSON)+=SIGN(rt);MAXSUM(RSON)+=SIGN(rt);MINSUM(RSON)+=SIGN(rt);SIGN(rt)=0;
}
void buildtree(int l,int r,int rt){LSIDE(rt)=l;RSIDE(rt)=r;SIGN(rt)=0;if(l==r){MAXSUM(rt)=MINSUM(rt)=val[pos[l]];MAXL(rt)=MAXR(rt)=0;return;}int mid=l+r>>1;buildtree(l,mid,LSON);buildtree(mid+1,r,RSON);pushup(rt);
}
void update(int l,int r,long long c,int rt){if(l<=LSIDE(rt)&&RSIDE(rt)<=r){SIGN(rt)+=c;MAXSUM(rt)+=c;MINSUM(rt)+=c;return;}pushdown(rt);int mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)update(l,r,c,LSON);if(mid<r)update(l,r,c,RSON);pushup(rt);
}
Segment_Tree query(int l,int r,int c,int rt){if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return b[rt];pushdown(rt);int mid=LSIDE(rt)+RSIDE(rt)>>1;if(r<=mid)return query(l,r,c,LSON);if(mid<l)return query(l,r,c,RSON);Segment_Tree ans,lson,rson;lson=query(l,r,c,LSON);rson=query(l,r,c,RSON);ans.maxn=max(lson.maxn,rson.maxn);ans.minn=min(lson.minn,rson.minn);if(c==1)ans.maxr=max(lson.maxn-rson.minn,max(lson.maxr,rson.maxr));elseans.maxl=max(rson.maxn-lson.minn,max(lson.maxl,rson.maxl));return ans;
}
void update_path(int x,int y,long long k){while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);update(id[top[x]],id[x],k,1);x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);update(id[x],id[y],k,1);
}
void solve(int x,int y){int top_x=0,top_y=0;long long ans=0;Segment_Tree s;while(top[x]!=top[y]){if(deep[top[x]]>deep[top[y]]){s=query(id[top[x]],id[x],1,1);ans=max(ans,s.maxr);top_x++;min_x[top_x]=s.minn;max_x[top_x]=s.maxn;x=fa[top[x]];}else{s=query(id[top[y]],id[y],2,1);ans=max(ans,s.maxl);top_y++;min_y[top_y]=s.minn;max_y[top_y]=s.maxn;y=fa[top[y]];}}if(deep[x]>deep[y]){s=query(id[y],id[x],1,1);ans=max(ans,s.maxr);top_x++;min_x[top_x]=s.minn;max_x[top_x]=s.maxn;}else{s=query(id[x],id[y],2,1);ans=max(ans,s.maxl);top_y++;min_y[top_y]=s.minn;max_y[top_y]=s.maxn;}for(int i=top_y;i>=1;i--){top_x++;min_x[top_x]=min_y[i];max_x[top_x]=max_y[i];}long long maxn=-MAX,minn=MAX;for(int i=1;i<=top_x;i++){ans=max(ans,max_x[i]-minn);minn=min(minn,min_x[i]);}for(int i=top_x;i>=1;i--){ans=max(ans,maxn-min_x[i]);maxn=max(maxn,max_x[i]);}if(ans<0)printf("0\n");else printf("%lld\n",ans);
}
void work(){int x,y,k;while(m--){x=read();y=read();k=read();solve(x,y);update_path(x,y,k);}
}
void init(){int x,y;n=read();for(int i=1;i<=n;i++)val[i]=read();for(int i=1;i<n;i++){x=read();y=read();add(x,y);}m=read();deep[1]=1;dfs1(1);dfs2(1,1);buildtree(1,n,1);
}
int main(){init();work();return 0;
}

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9562845.html

BZOJ3999: [TJOI2015]旅游相关推荐

  1. BZOJ3999 [TJOI2015]旅游

    水题--链剖然后维护区间最大值,最小值,和区间从左往右走的答案,还有从右往左走的答案即可 #include<iostream> #include<cstdlib> #inclu ...

  2. bzoj 3999: [TJOI2015]旅游(树链剖分)

    3999: [TJOI2015]旅游 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 423  Solved: 214 [Submit][Status ...

  3. [TJOI2015]旅游

    问题描述 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会选择从A城市买入 ...

  4. 【BZOJ3999】旅游,树链剖分中的有向信息合并

    Time:2016.05.26 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: (调了好久发现是链剖打错了) 线性版本的话可以去看水果姐逛水果店Ⅰ 这个放到了树上,还加了个修改操作 ...

  5. [暑假的bzoj刷水记录]

    (这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊  堆一起算了 隔一段更新一下.  7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...

  6. 退役前的做题记录2.0

    退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...

  7. 2022-2028年中国康养旅游行业市场竞争力分析及发展策略分析报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国康养旅游行业市场行业相关概述.中国康养旅 ...

  8. 2022-2028年中国老年旅游市场深度调研及开发战略研究报告

    [报告类型]产业研究 [报告价格]¥4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国老年旅游行业市场行业相关概述.中国老年 ...

  9. 2022-2028年中国房车旅游行业深度调研及投资前景预测报告

    [报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了房车旅游行业相关概述.中国房车旅游行业运行环境.分析了中国房车旅游行 ...

最新文章

  1. mysql维护索引_高性能的MySQL(5)索引策略-索引和表的维护
  2. Linux free -m 详细说明
  3. c语言计算文件摘要值,c语言文件操作摘要.ppt
  4. Spring Boot 使用常见问题
  5. 信息学奥赛一本通(2016:【例4.1】for循环求和)
  6. RHEL7 -- 使用Chrony设置时间与时钟服务器同步
  7. docker容器中的网络原理(单机模式下的容器网络)
  8. 10个最新优秀手机应用界面设计实例
  9. mac安装mysql出错_Mac 安装MySQL过程遇到的问题
  10. 非功能测试之本地化和国际化测试
  11. 班门弄斧之机械设计理论
  12. MFSPV: A Multi-Factor Secured and Lightweight Privacy-Preserving Authentication Schem
  13. Python语法概念基础
  14. centos安装图形化界面及vnc-server连接
  15. Merriam-Webster‘s Vocabular Builder ( BELL )
  16. gitlab runner 使用案例
  17. jeesite4 下拉框
  18. 黑苹果传统BIOS引导安装
  19. 爱婴室主要股东再现减持:莫锐伟、王云亦是如此,业绩表现不理想
  20. 喜报|中新赛克OceanMind独家赞助的DSE期刊被ESCI收录

热门文章

  1. 如何看Linux服务器是否被攻击
  2. 从未有过的空闲学校生活
  3. matplotlib一些常用知识点的整理,
  4. Java网络01基本网络概念
  5. Kubernetes - - k8s - v1.12.3 OpenLDAP统一认证
  6. 浅析微信支付:申请退款、退款回调接口、查询退款
  7. oracle部署--安装oracle软件与部署单实例数据库
  8. 第一阶段:前端开发_Mysql——表与表之间的关系
  9. 只能输入正整数 以及常用的正则表达式
  10. 网络配置 rpm yum