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

省选前写的没发

题意:给定一个有nn个节点的树,每个点又点权vivi,每次选取一条树链[a,b],求出max(vj−vi),其中i,j∈[a,b]i,j∈[a,b]且i出现在j前面,最后树链[a,b][a,b]上的点点权都加上v′

显然的链剖转为序列问题,但线段树打起来太操蛋了,所以我选择了打分块;

由于要满足i出现在j的前面,所以我们必须按照路径的顺序来处理,所以跳lca的时候要把路径存下来,并且终点到lca的路径要逆序处理,所以代码很冗长。

具体做法的话就是:

对于路径按顺序一直维护一个最小值,由于按照顺序处理,所以保证了i在j前面

对于散点就直接与最小值做差比较,并更新最小值

对于整块,就为维护一个整块内的最大值,最小值,和这一个块单独能产生的最大贡献;

获益的话再与(最大值-不算这个块的最小值)和(这个块的单独贡献)取max;

然后用块内最小值更新最小值

更改暴力重构即可

nlog*sqrt(n);卡时过的

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define int long long
using namespace std;
const int N=200050;
const int Inf=(1ll<<60);
int gi(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int cnt,head[N],to[N],nxt[N],top[N],son[N],size[N],fa[N],deep[N],dfn[N],id[N],ed[N],v[N];
int block,pos[N],L[N],R[N],MAX[N],MIN[N],MAXV[N],tot,tot2,tt,sum,add[N];
int MAX2[N],MIN2[N],MAXV2[N];
int minn,maxv;
struct data{
int l,r;
}q[N],q2[N];
bool cmp1(data a,data b){return a.r>b.r;}
bool cmp2(data a,data b){return a.r<b.r;}
inline int Min(int a,int b){
return a<b?a:b;
} inline int Max(int a,int b){
return a>b?a:b;
}
inline void dfs1(RG int x,RG int f){
deep[x]=deep[f]+1;size[x]=1;
for(RG int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=f){
fa[y]=x;dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
}
inline void dfs2(RG int x,RG int f){
dfn[x]=++sum;id[sum]=x;top[x]=f;
if(son[x]) dfs2(son[x],f);
for(RG int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
}
inline int lca(RG int x,RG int y){
tot=0;int fl=1;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y),fl^=1;
if(fl) q[++tot]=(data){dfn[top[x]],dfn[x]};
else q2[++tot2]=(data){dfn[top[x]],dfn[x]};
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y),fl^=1;
if(fl) q[++tot]=(data){dfn[y],dfn[x]};
else q2[++tot2]=(data){dfn[y],dfn[x]};
return y;
}
inline void lnk(RG int x,RG int y){
to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
}
inline void rebuild(RG int i){
MAX[i]=v[id[L[i]]],MIN[i]=v[id[L[i]]],MAXV[i]=0;
for(RG int j=L[i]+1;j<=R[i];j++){
MAXV[i]=Max(MAXV[i],v[id[j]]-MIN[i]);
MAX[i]=Max(MAX[i],v[id[j]]);MIN[i]=Min(MIN[i],v[id[j]]);
}
MAX2[i]=MAX[i],MIN2[i]=v[id[R[i]]],MAXV2[i]=0;
for(RG int j=R[i]-1;j>=L[i];j--){
MAXV2[i]=Max(MAXV2[i],v[id[j]]-MIN2[i]);
MIN2[i]=Min(MIN2[i],v[id[j]]);
}
}
inline void update(RG int l,RG int r,RG int c){
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++) v[id[i]]+=c;
rebuild(pos[l]);
}
else{
for(RG int i=l;i<=R[pos[l]];i++) v[id[i]]+=c;
rebuild(pos[l]);
for(RG int i=pos[l]+1;i<=pos[r]-1;i++) add[i]+=c;
for(RG int i=L[pos[r]];i<=r;i++) v[id[i]]+=c;
rebuild(pos[r]);
}
}
inline void query(RG int l,RG int r){
if(pos[l]==pos[r]){
for(RG int i=l;i<=r;i++){
maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
minn=Min(minn,v[id[i]]+add[pos[l]]);
}
}
else{
for(RG int i=l;i<=R[pos[l]];i++){
maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
minn=Min(minn,v[id[i]]+add[pos[l]]);
}
for(RG int i=pos[l]+1;i<=pos[r]-1;i++){
maxv=Max(maxv,max(MAX[i]+add[i]-minn,MAXV[i]));
minn=Min(minn,MIN[i]+add[i]);
}
for(RG int i=L[pos[r]];i<=r;i++){
maxv=Max(maxv,v[id[i]]+add[pos[r]]-minn);
minn=Min(minn,v[id[i]]+add[pos[r]]);
}
}
}
inline void query2(RG int r,RG int l){
if(pos[l]==pos[r]){
for(RG int i=r;i>=l;i--){
maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
minn=Min(minn,v[id[i]]+add[pos[l]]);
}
}
else{
for(RG int i=r;i>=L[pos[r]];i--){
maxv=Max(maxv,v[id[i]]+add[pos[r]]-minn);
minn=Min(minn,v[id[i]]+add[pos[r]]);
}
for(RG int i=pos[r]-1;i>=pos[l]+1;i--){
maxv=Max(maxv,Max(MAX2[i]+add[i]-minn,MAXV2[i]));
minn=Min(minn,MIN2[i]+add[i]);
}
for(RG int i=R[pos[l]];i>=l;i--){
maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
minn=Min(minn,v[id[i]]+add[pos[l]]);
}
}
}
main()
{
int n=gi();for(int i=1;i<=n;i++) v[i]=gi();
for(RG int i=1;i<n;i++){
int x=gi(),y=gi();lnk(x,y);
}
dfs1(1,0);dfs2(1,1);
block=sqrt(n);sum=n/block;
if(n%block) sum++;
for(RG int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
for(RG int i=1;i<=sum;i++) L[i]=(i-1)*block+1,R[i]=i*block;
R[sum]=n;
for(RG int i=1;i<=sum;i++){
MAX[i]=v[id[L[i]]],MIN[i]=v[id[L[i]]];
for(RG int j=L[i]+1;j<=R[i];j++){
MAXV[i]=Max(MAXV[i],v[id[j]]-MIN[i]);
MAX[i]=Max(MAX[i],v[id[j]]);MIN[i]=Min(MIN[i],v[id[j]]);
}
MAX2[i]=v[id[R[i]]],MIN2[i]=v[id[R[i]]];
for(RG int j=R[i]-1;j>=L[i];j--){
MAXV2[i]=Max(MAXV2[i],v[id[j]]-MIN2[i]);
MAX2[i]=Max(MAX2[i],v[id[j]]);MIN2[i]=Min(MIN2[i],v[id[j]]);
}
}
int Q=gi();
for(RG int i=1;i<=Q;i++){
int a=gi(),b=gi(),c=gi();
tot=0,tot2=0;lca(a,b);
minn=Inf,maxv=-Inf;
for(RG int j=1;j<=tot;j++) query2(q[j].r,q[j].l);
for(RG int j=tot2;j>=1;j--) query(q2[j].l,q2[j].r);
for(RG int j=1;j<=tot;j++) update(q[j].l,q[j].r,c);
for(RG int j=1;j<=tot2;j++) update(q2[j].l,q2[j].r,c);
if(maxv<0) puts("0");
else printf("%lld\n",maxv);
}
return 0;
}

  

bzoj 3999: [TJOI2015]旅游的更多相关文章

  1. bzoj 3999: [TJOI2015]旅游 LCT

    没啥难的,inf 的值设小了调了半天~ code: #include <bits/stdc++.h> #define N 50003 #define lson t[x].ch[0] #de ...

  2. 【BZOJ3999】[TJOI2015]旅游(Link-Cut Tree)

    [BZOJ3999][TJOI2015]旅游(Link-Cut Tree) 题面 BZOJ 洛谷 题解 一道不难的\(LCT\)题(用树链剖分不是为难自己吗,这种有方向的东西用\(LCT\)不是方便那 ...

  3. BZOJ 3999 旅游

    .......好长啊. #include<iostream> #include<cstdio> #include<cstring> #include<algo ...

  4. BZOJ3999 [TJOI2015]旅游

    题面:给定一个有$n$个节点的树,每个点又点权$v_i$,每次选取一条树链$[a, b]$,求出$max(v_i - v_j)$,其中$i, j \in [a, b]$且$i$出现在$j$前面,最后树 ...

  5. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

  6. BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )

    先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include ...

  7. bzoj 3996: [TJOI2015]线性代数 [最小割]

    3996: [TJOI2015]线性代数 题意:给出一个NN的矩阵B和一个1N的矩阵C.求出一个1*N的01矩阵A.使得 \(D=(A * B-C)* A^T\)最大.其中A^T为A的转置.输出D.每 ...

  8. BZOJ 3997: [TJOI2015]组合数学 [偏序关系 DP]

    3997: [TJOI2015]组合数学 题意:\(n*m:\ n \le 1000\)网格图,每个格子有权值.每次从左上角出发,只能向下或右走.经过一个格子权值-1.至少从左上角出发几次所有权值为0 ...

  9. BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status] ...

随机推荐

  1. MySQL错误:2003-Can't connect to MySQL server on 'localhost'(10061 "unknown error")

    今天数据库出了一点错误之后决定重装一下,结果卡在了一个问题上,连装了5遍,加上网上各种配置教程都没能结局,错误如下图所示: 最后忽然想到会不会是因为每一次卸载的时候没有彻底卸载干净,然后就彻彻底底卸载 ...

  2. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

  3. Ceph luminous 安装配置

    Ceph luminous 安装配置 #环境centos7 , Ceph V12 openstack pike 与 ceph 集成 http://www.cnblogs.com/elvi/p/7897 ...

  4. JAVA基础-JDBC二(常用的开源工具)

    一.连接池 在实际的开发应用中,我们常常会对数据库进行大量的高并发的访问,而最原始的连接和操作方式并不能满足这种大量的访问,程序员为了追求更方便.更快捷.更科学安全的开发.第三方的工具类和Dao层的框 ...

  5. VMware中克隆虚拟机出现eth0改变为eth1情况

    解决如下: 查看复制虚拟机网卡信息如下: root@jcfx-2 ~]# ifconfig eth1 Link encap:Ethernet HWaddr 00:0C:29:CC:32:63 inet ...

  6. FastDFS教程Ⅲ-文件服务器扩容

    1.简介     FastDFS文件服务器在设计时,为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式.存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是 ...

  7. Java分布式锁实现详解

    在进行大型网站技术架构设计以及业务实现的过程中,多少都会遇到需要使用分布式锁的情况.那么问题也就接踵而至,哪种分布式锁更适合我们的项目? 下面就这个问题,我做了一些分析: 分布式锁现状: 目前几乎很多 ...

  8. CountDownLatch的实现原理

    CountDownLatch是java并发包中辅助并发的工具类,目的是让并发运行的代码在某一个执行点阻塞,直到所有条件都满足,这里的条件就是调用countDown()方法,有点类似计数器的功能. 用法 ...

  9. web前端素材整理汇总

    最近一直搞前端开发,整理下前端用的一些常用素材,分享给大家 框架类 Vue:https://cn.vuejs.org/ iview:https://www.iviewui.com/ 插件类 Jquer ...

  10. hdoj 1285 确定比赛名次 【拓扑排序】

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...