2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)
传送门
树链剖分菜题。
题意不清差评。
题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值。
思路:
考虑暴力:维护路径的前缀最小值和后缀最大值然后更新答案。
然后可以用线段树优化这个过程。
对于当前的线段树节点,它的答案=max(左儿子答案,右儿子答案,右儿子最大值−左儿子最小值)max(左儿子答案,右儿子答案,右儿子最大值-左儿子最小值)max(左儿子答案,右儿子答案,右儿子最大值−左儿子最小值)
然后由于路径是有向的,因此在树链剖分两边跳的时候也要考虑方向的因素。
所以还要维护一个跟上面对称的信息,即路径的前缀最大值和后缀最小值。
然后就没了。
代码:
#include<bits/stdc++.h>
#define ri register int
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
const int N=5e4+5;
const ll inf=1e18;
int n,tot=0,a[N],num[N],pred[N],siz[N],hson[N],top[N],dep[N],fa[N];
vector<int>e[N];
struct Node{
int l,r;ll mx,mn,det[2],add;
Node(){l=r=add=0,mx=-inf,mn=inf,det[0]=det[1]=-inf;}
}T[N<<2];
inline Node operator+(const Node&a,const Node&b){
Node ret;
ret.l=a.l,ret.r=b.r,ret.add=0;
ret.mx=max(a.mx,b.mx),ret.mn=min(a.mn,b.mn);
ret.det[0]=max(max(a.det[0],b.det[0]),b.mx-a.mn);
ret.det[1]=max(max(a.det[1],b.det[1]),a.mx-b.mn);
return ret;
}
inline void pushnow(int p,ll v){T[p].mx+=v,T[p].mn+=v,T[p].add+=v;}
inline void pushdown(int p){if(T[p].add)pushnow(lc,T[p].add),pushnow(rc,T[p].add),T[p].add=0;}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r){T[p].mx=T[p].mn=a[pred[l]];return;}
build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc];
}
inline void update(int p,int ql,int qr,ll v){
if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
T[p]=T[lc]+T[rc];
}
inline Node query(int p,int ql,int qr){
if(ql<=T[p].l&&T[p].r<=qr)return T[p];
pushdown(p);
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
return query(lc,ql,mid)+query(rc,mid+1,qr);
}
inline void change(int x,int y,ll v){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(1,num[top[x]],num[x],v),x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
update(1,num[y],num[x],v);
}
inline int lca(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline ll ask(int x,int y){
bool f=x+y==11;
int t=lca(x,y);
Node t1,t2;
while(top[x]^top[t])t1=query(1,num[top[x]],num[x])+t1,x=fa[top[x]];
while(top[y]^top[t])t2=query(1,num[top[y]],num[y])+t2,y=fa[top[y]];
if(y==t)t1=query(1,num[t],num[x])+t1;
else t2=query(1,num[t],num[y])+t2;
return max(max(t1.det[1],t2.det[0]),max(0ll,t2.mx-t1.mn));
}
void bfs(){
static int q[N],hd,tl;
q[hd=tl=1]=1;
while(hd<=tl){
int p=q[hd++];
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p])continue;
fa[v]=p,dep[v]=dep[p]+1,q[++tl]=v;
}
}
for(ri i=n,p;i;--i){
p=q[i];
if(i^1){
siz[fa[p]]+=siz[p];
if(siz[p]>siz[hson[fa[p]]])hson[fa[p]]=p;
}
}
q[hd=tl=n]=1;
while(hd<=tl){
int p=q[hd++];
top[p]=hson[fa[p]]==p?top[fa[p]]:p;
pred[num[p]=++tot]=p;
if(!hson[p])continue;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p]||v==hson[p])continue;
q[--hd]=v;
}
q[--hd]=hson[p];
}
}
int main(){
n=read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
bfs(),build(1,1,n);
for(ri tt=read(),u,v;tt;--tt){
u=read(),v=read();
ll w=read();
cout<<ask(u,v)<<'\n';
change(u,v,w);
}
return 0;
}
2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)的更多相关文章
- BZOJ3999:[TJOI2015]旅游(树链剖分)
Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...
- BZOJ 2157: 旅游( 树链剖分 )
树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...
- BZOJ2157旅游——树链剖分+线段树
题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...
- BZOJ2157: 旅游 树链剖分 线段树
http://www.lydsy.com/JudgeOnline/problem.php?id=2157 在对树中数据进行改动的时候需要很多pushdown(具体操作见代码),不然会wa,大概原因 ...
- 2019 ACM-ICPC 西安全国邀请赛 E-Tree 树链剖分+线段树
题意 给一颗带点权的树,三种操作 \(1~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]|t\) \(2~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]\& ...
- BZOJ 2157: 旅游 (树链剖分+线段树)
树链剖分后线段树维护区间最大最小值与和. 支持单点修改与区间取反. 直接写个区间取反标记就行了.线段树板题.(200行6000B+ 1A警告) #include <cstdio> #inc ...
- 2019.01.19 bzoj3653: 谈笑风生(长链剖分优化dp)
传送门 长链剖分优化dpdpdp水题. 题意简述:给一棵树,mmm次询问,每次给一个点aaa和一个值kkk,询问满足如下条件的三元组(a,b,c)(a,b,c)(a,b,c)的个数. a,b是c的祖先 ...
- 【BZOJ2157】旅游 树链剖分+线段树
[BZOJ2157]旅游 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本 ...
- 洛谷 P1505 [国家集训队]旅游 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ...
随机推荐
- c# 关闭和重启.exe程序
Process[] myprocess = Process.GetProcessesByName("a"); if (myprocess.Count() > 0)//判断如果 ...
- Codeforces Beta Round #65 (Div. 2)
Codeforces Beta Round #65 (Div. 2) http://codeforces.com/contest/71 A #include<bits/stdc++.h> ...
- YII2中操作数据库的方式
一.以createCommand方式: // YII2中通过createCommand来处理数据库 // 查询多条记录 // {{%user}} 表示如果设置了表前缀,YII会自动帮你替换 $data ...
- spirng中的asm与jdk不兼容<已解决>
转载自:spirng中的asm与jdk不兼容<已解决> 前言 不知道前面对eclipse做了什么,使用maven来创建项目,然后转成web,启动的时候一直报错.我弄了好久,还是无法解决,先 ...
- input框和文字对齐问题
css样式解决! style="vertical-align: text-bottom;margin-bottom: 2px;"一.问题产生的条件对于14像素大小的字体是没有本篇所 ...
- jQuery 实例
选择器 $(this).hide() 隐藏当前的 HTML 元素. $("p").hide() 隐藏所有 <p> 元素. $(".test").hi ...
- 4.Mysql中的运算符
4.Mysql中的运算符运算符用来连接表达式.运算符包括:算术运算符.比较运算符.逻辑运算符.位运算符. 4.1 算术运算符算术运算符包括加(+).减(-).乘(*).除(/).取模(%,MOD) 5 ...
- OKI系列针式打印机更换色带图解教程
色带一直换不好,今天找到一个带图的教程,收藏一下 打开新色带的包装后,我们可以仔细观察一下新色带,找到里面带有一段“扭曲”色带的位置,这段色带就是:“莫比乌斯带”结构. 找到“莫比乌斯带”结构(就是有 ...
- PAT 1023 组个最小数 (20)(代码+思路)
1023 组个最小数 (20)(20 分) 给定数字0-9各若干个.你可以以任意顺序排列这些数字,但必须全部使用.目标是使得最后得到的数尽可能小(注意0不能做首位).例如:给定两个0,两个1,三个5, ...
- MAC/Xcode简单操作命令
快捷键: command(windows) + c: 复制 command + V : 粘贴 command + x: 剪切(只在当前应用程序内有效) 在mac系统下表示剪切功能: 先command ...