题目大意:

给定n (表示树有n个结点)

接下来n行给定n个点的点权(在这个点上买鸡或者卖鸡的价钱就是点权)

接下来n-1行每行给定 x y 表示x结点和y结点之间有一条边

给定q (表示有q个询问)

接下来q行 每行给定 x y v

查询x到y的路径上 先买鸡再卖鸡能够赢得的最大利润

买卖完后 x到y整条路径的点权都要加上v

因为必须先买再卖 所以这个买卖有方向性

就得维护区间 从左向右买卖的最大利润maxl 和 从右向左买卖的最大利润maxr

而 从左向右买卖的利润maxl = 右子区间的最大值 - 左子区间的最小值 (maxr同理)

所以还要维护区间 最大值maxw 和 最小值minw

整条路径都加上v 区间更新还要加个 lazy 标记

查询时 最后路径被分成 LCA-x 和 LCA-y 由LCA到底部的两段

所以按方向更新答案应该 ans=max( LCA-y.maxl , LCA-x.maxr )

最后还要通过 ans=max( ans , LCA-y.maxw - LCA-x.minw ) 更新一下答案

最后 我的代码里 线段树的 pushUp() 操作直接调用了 Merge() 函数

而 lazy 在合并前已经更新过了 防止出错 将已得到的 lazy 传参赋值

而查询时的合并操作 只需要查询线段树 不需要修改 所以lazy直接传个没用的0就好了

#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define mem(i,j) memset(i,j,sizeof(i))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,n,1 const int maxn=1e5+;
int n, q, w[maxn]; struct IntervalTree {
struct EDGE { int to,ne; }e[maxn<<];
int head[maxn], tot;
void addE(int u,int v) {
e[tot].to=v;
e[tot].ne=head[u];
head[u]=tot++;
} int fa[maxn], son[maxn], dep[maxn], num[maxn];
int top[maxn], p[maxn], fp[maxn], pos; void init() {
tot=; mem(head,);
pos=; mem(son,);
} struct TREE {
int lazy;
int maxw,minw; // 区间极值
int maxl,maxr; // 从左开始最大差值 从右开始最大差值
TREE(){ lazy=maxw=minw=maxl=maxr=; }
}tree[maxn<<]; // --------------------以下是线段树------------------------- TREE Merge(TREE L,TREE R,int lazy) {
if(R.maxw==) return L;
TREE ans; ans.lazy=lazy;
ans.maxw=max(L.maxw,R.maxw);
ans.minw=min(L.minw,R.minw);
ans.maxl=max(max(L.maxl,R.maxl),R.maxw-L.minw);
ans.maxr=max(max(L.maxr,R.maxr),L.maxw-R.minw);
return ans;
}
void pushUp(int rt) {
tree[rt]=Merge(tree[rt<<],tree[rt<<|],tree[rt].lazy);
}
void pushDown(int rt) {
if(tree[rt].lazy) {
int t=tree[rt].lazy;
tree[rt<<].minw+=t;
tree[rt<<].maxw+=t;
tree[rt<<].lazy+=t;
tree[rt<<|].minw+=t;
tree[rt<<|].maxw+=t;
tree[rt<<|].lazy+=t;
tree[rt].lazy=;
} // 差值不变 不需要更新
}
void build(int l,int r,int rt) {
tree[rt].lazy=;
if(l==r) {
tree[rt].maxw=tree[rt].minw=fp[l];
tree[rt].maxl=tree[rt].maxr=;
return;
}
int m=(l+r)>>;
build(lson), build(rson);
pushUp(rt);
}
void update(int L,int R,int v,int l,int r,int rt) {
if(l==L && R==r) {
tree[rt].lazy+=v;
tree[rt].maxw+=v;
tree[rt].minw+=v;
return;
}
pushDown(rt);
int m=(l+r)>>;
if(R<=m) update(L,R,v,lson);
else if(L>m) update(L,R,v,rson);
else update(L,m,v,lson),update(m+,R,v,rson);
pushUp(rt);
}
TREE query(int L,int R,int l,int r,int rt) {
if(L==l && r==R) return tree[rt];
pushDown(rt);
int m=(l+r)>>;
if(R<=m) return query(L,R,lson);
else if(L>m) return query(L,R,rson);
else return Merge(query(L,m,lson),query(m+,R,rson),tree[rt].lazy);
} // --------------------以上是线段树------------------------- // --------------------以下是树链剖分------------------------- void dfs1(int u,int pre,int d) {
dep[u]=d; fa[u]=pre; num[u]=;
for(int i=head[u];i;i=e[i].ne) {
int v=e[i].to;
if(v!=fa[u]) {
dfs1(v,u,d+);
num[u]+=num[v];
if(!son[u] || num[v]>num[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int sp) {
top[u]=sp; p[u]=++pos; fp[p[u]]=w[u];
if(!son[u]) return;
dfs2(son[u],sp);
for(int i=head[u];i;i=e[i].ne) {
int v=e[i].to;
if(v!=son[u] && v!=fa[u])
dfs2(v,v);
}
}
int solve(int x,int y,int v) {
int fx=top[x], fy=top[y];
TREE ans1, ans2;
while(fx!=fy) {
if(dep[fx]>dep[fy]) {
ans1=Merge(query(p[fx],p[x],root),ans1,);
update(p[fx],p[x],v,root);
x=fa[fx];
} else {
ans2=Merge(query(p[fy],p[y],root),ans2,);
update(p[fy],p[y],v,root);
y=fa[fy];
}
fx=top[x], fy=top[y];
}
if(p[x]>p[y]) {
ans1=Merge(query(p[y],p[x],root),ans1,);
update(p[y],p[x],v,root);
}
else {
ans2=Merge(query(p[x],p[y],root),ans2,);
update(p[x],p[y],v,root);
}
int ans=max(ans1.maxr,ans2.maxl);
if(ans1.minw) ans=max(ans,ans2.maxw-ans1.minw);
return ans;
} // --------------------以上是树链剖分------------------------- void initQTree() {
dfs1(,,), dfs2(,);
build(root);
}
}T; int main()
{
int t; scanf("%d",&t);
while(t--) {
scanf("%d",&n);
T.init();
for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<=n;i++) {
int u,v; scanf("%d%d",&u,&v);
T.addE(u,v); T.addE(v,u);
}
T.initQTree();
scanf("%d",&q);
while(q--) {
int x,y,v; scanf("%d%d%d",&x,&y,&v);
printf("%d\n",T.solve(x,y,v));
}
} return ;
}

HDU 5052 /// 树链剖分+线段树区间合并的更多相关文章

  1. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  2. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  3. 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并

    题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...

  4. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  5. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  6. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  7. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. Zabbix 历史数据存储到 Elasticsearch

    Zabbix 历史数据存储到 Elasticsearch Zabbix 3.4.6 版本开始支持历史数据存储到 Elasticsearch, 早就想测试这个功能,最近有个需求需保存 zabbix 的历 ...

  2. Python 操作excel常见异常

    一.使用xlrd模块读取excel: 1.报错:IndexError: list index out of range,如下图 解决方法:reading_sheet.cell(1,0).value中c ...

  3. C++子类父类构造函数的关系

    在C++中子类继承和调用父类的构造函数方法 构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法).因此,在创建子类对象 ...

  4. 20140730 word标题样式 数组

    1.word 标题四, 右键更新 自己也可以新建标题样式 2.数组 连续内存,空间复杂度高(即使数组存在一个元素,占据的空间的大小不变),时间复杂度低(0(1)访问),内存分配一次性完成

  5. HTML中<frameset>标签不显示的问题

    啥都不说,先上代码 <html> <head> <title>index</title> <meta content = 'text/html'; ...

  6. Python的datetime模块使用

    两个常量 MAXYEAR:9999 MINYEAR:1 五个类 datetime.datetime:日期时间类 datetime.date:日期类 datetime.time:时间类 datetime ...

  7. 只用200行Go代码写一个自己的区块链!(转)

    区块链是目前最热门的话题,广大读者都听说过比特币,或许还有智能合约,相信大家都非常想了解这一切是如何工作的.这篇文章就是帮助你使用 Go 语言来实现一个简单的区块链,用不到 200 行代码来揭示区块链 ...

  8. python--接口类与抽象类

    一. 继承有两种用途: """ 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了 ...

  9. js的基本语法规范

    1.不要在同一行声明多个变量: 2.使用===/!==来比较true/false的返回值: 3.使用字面量替代new Array这种形式: 4.不要使用全局函数: 5.switch语句必须带有defa ...

  10. 关于while循环中的break和continue的区别

    while循环如果不加条件限制的话,它会一直循环下去,那么问题就来了,如果我不用条件去终止while循环的话,那么我该用什么方法去终止呢? 你可以选择两种终止while循环的方法 1.break  强 ...