【BZOJ3999】【TJOI2015】旅游 树剖
题目大意
给你一棵树,有\(n\)个点。有\(q\)个操作,每次要你从\(x\)到\(y\)的路径上选两个点,使得距离\(x\)比较远的点的点权\(-\)距离\(x\)比较近的点的点权最大,然后把这条路径上所有点的点权\(+v\)。
\(n,q\leq 50000\)
题解
这种题没什么意思,直接树剖就好了。
线段树上每个点记录最大值,最小值,从左往右走和从右往左走的最大收益。
时间复杂度:\(O(n+q\log^2 n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
struct pp
{
ll ma,mi;
ll s1,s2;
pp()
{
ma=mi=s1=s2=0;
}
};
pp merge(pp a,pp b)
{
pp c;
c.s1=max(b.ma-a.mi,max(a.s1,b.s1));
c.s2=max(a.ma-b.mi,max(a.s2,b.s2));
c.ma=max(a.ma,b.ma);
c.mi=min(a.mi,b.mi);
return c;
}
pp rev(pp a)
{
swap(a.s1,a.s2);
return a;
}
int c[100010];
namespace seg
{
struct tree
{
int ls,rs;
int l,r;
ll t;
pp s;
};
tree a[100010];
int cnt;
void build(int &p,int l,int r)
{
p=++cnt;
a[p].l=l;
a[p].r=r;
if(l==r)
{
a[p].s.ma=a[p].s.mi=c[l];
return;
}
int mid=(l+r)>>1;
build(a[p].ls,l,mid);
build(a[p].rs,mid+1,r);
a[p].s=merge(a[a[p].ls].s,a[a[p].rs].s);
}
void add(int p,ll v)
{
a[p].s.ma+=v;
a[p].s.mi+=v;
a[p].t+=v;
}
void push(int p)
{
if(a[p].t&&a[p].ls!=a[p].r)
{
add(a[p].ls,a[p].t);
add(a[p].rs,a[p].t);
a[p].t=0;
}
}
void add(int p,int l,int r,int v)
{
if(l<=a[p].l&&r>=a[p].r)
{
add(p,v);
return;
}
push(p);
int mid=(a[p].l+a[p].r)>>1;
if(l<=mid)
add(a[p].ls,l,r,v);
if(r>mid)
add(a[p].rs,l,r,v);
a[p].s=merge(a[a[p].ls].s,a[a[p].rs].s);
}
pp query(int p,int l,int r)
{
if(l<=a[p].l&&r>=a[p].r)
return a[p].s;
push(p);
int mid=(a[p].l+a[p].r)>>1;
if(r<=mid)
return query(a[p].ls,l,r);
if(l>mid)
return query(a[p].rs,l,r);
return merge(query(a[p].ls,l,r),query(a[p].rs,l,r));
}
}
struct graph
{
int v[100010];
int t[100010];
int h[50010];
int n;
graph()
{
n=0;
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
graph g;
struct p
{
int f,w,t,d,ms,s;
};
p a[100010];
int wcnt;
void dfs1(int x,int fa,int dep)
{
a[x].f=fa;
a[x].d=dep;
a[x].s=1;
int ms=0;
int i;
for(i=g.h[x];i;i=g.t[i])
if(g.v[i]!=fa)
{
dfs1(g.v[i],x,dep+1);
if(a[g.v[i]].s>ms)
{
ms=a[g.v[i]].s;
a[x].ms=g.v[i];
}
a[x].s+=a[g.v[i]].s;
}
}
void dfs2(int x,int top)
{
a[x].w=++wcnt;
a[x].t=top;
if(!a[x].ms)
return;
dfs2(a[x].ms,top);
int i;
for(i=g.h[x];i;i=g.t[i])
if(g.v[i]!=a[x].f&&g.v[i]!=a[x].ms)
dfs2(g.v[i],g.v[i]);
}
int prize[100010];
int rt;
ll query(int x,int y,int z)
{
pp s1,s2;
s1.ma=s1.mi=0x7fffffff;
s2.ma=s2.mi=-0x7fffffff;
while(a[x].t!=a[y].t)
if(a[a[x].t].d>a[a[y].t].d)
{
s1=merge(s1,rev(seg::query(rt,a[a[x].t].w,a[x].w)));
seg::add(rt,a[a[x].t].w,a[x].w,z);
x=a[a[x].t].f;
}
else
{
s2=merge(seg::query(rt,a[a[y].t].w,a[y].w),s2);
seg::add(rt,a[a[y].t].w,a[y].w,z);
y=a[a[y].t].f;
}
if(a[x].w<a[y].w)
{
s2=merge(seg::query(rt,a[x].w,a[y].w),s2);
seg::add(rt,a[x].w,a[y].w,z);
}
else
{
s1=merge(s1,rev(seg::query(rt,a[y].w,a[x].w)));
seg::add(rt,a[y].w,a[x].w,z);
}
s1=merge(s1,s2);
return s1.s1;
}
int main()
{
open("bzoj3999");
int n,q;
scanf("%d",&n);
int i,x,y,z;
for(i=1;i<=n;i++)
scanf("%d",&prize[i]);
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
g.add(x,y);
g.add(y,x);
}
dfs1(1,0,1);
dfs2(1,1);
for(i=1;i<=n;i++)
c[a[i].w]=prize[i];
seg::build(rt,1,n);
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d%d",&x,&y,&z);
ll ans=query(x,y,z);
printf("%lld\n",ans);
}
return 0;
}
【BZOJ3999】【TJOI2015】旅游 树剖的更多相关文章
- BZOJ3999:[TJOI2015]旅游(树链剖分)
Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...
- BZOJ3999 [TJOI2015]旅游 【树剖 + 线段树】
题目 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会选择从A城市买入再 ...
- P1505 [国家集训队]旅游[树剖]
题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...
- 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)
传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...
- BZOJ3999 [TJOI2015]旅游
题面:给定一个有$n$个节点的树,每个点又点权$v_i$,每次选取一条树链$[a, b]$,求出$max(v_i - v_j)$,其中$i, j \in [a, b]$且$i$出现在$j$前面,最后树 ...
- 【BZOJ3999】[TJOI2015]旅游(Link-Cut Tree)
[BZOJ3999][TJOI2015]旅游(Link-Cut Tree) 题面 BZOJ 洛谷 题解 一道不难的\(LCT\)题(用树链剖分不是为难自己吗,这种有方向的东西用\(LCT\)不是方便那 ...
- BZOJ_2157_旅游_树剖+线段树
BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...
- BZOJ2157 旅游 【树剖 或 LCT】
题目 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径. ...
- luoguP1505旅游(处理边权的树剖)
/* luogu1505 非常简单的处理边权的树剖题. 在树上将一条边定向,把这条边的权值赋给这条边的出点 树剖的时候不计算lca权值即可 */ #include<bits/stdc++.h&g ...
随机推荐
- javaMail发邮件,激活用户账号
用javamail实现注册用户验证邮箱功能.用户注册后随机生成一个uuid作为用户的标识,传递给用户然后作为路径参数.发送html的内容到用户注册的邮箱里,若用户点击后去往的页面提交username和 ...
- vuex状态管理工具
父子组件之间的通信 props传递 父 向子单向传递:且每次 父组件更新时 子组件的props会跟着更新: 如果需要 子组件把数据传递给父组件,就需要在子组件上绑定自定事件 在子组件使用this ...
- 结对项目3-功能增强型带基本函数计算java计算器
-----------------------------------------------------实验报告------------------------------------------- ...
- Linux之磁盘挂载
1.查看磁盘分区情况: fdisk -l 可以看到,红框中的硬盘没有分区. 2.开始分区: fdisk /dev/vdb 3.格式化分区: mkfs.xfs 分区名 4.挂载磁盘 挂载方式1: 手动挂 ...
- windows中在vs code终端使用bash
vs code Visual Studio Code的缩写,很好用的一个编辑器. 终端 vs code的终端(命令行)在windows中,默认使用的是powershell,如下图所示: powersh ...
- CodeIgniter框架通过URL向控制器传递参数
通过URL传递参数的方法是GET,在CodeIgnter框架中,通过URL有两种方式向控制器传递参数: 一种是键值对的形式. 一种是类似于文件路径的形式,这个时候,不是以键值对的形式了,我们只传递值. ...
- MySQL之数据导入导出
日常开发中,经常会涉及到对于数据库中数据的导入与导出操作,格式也有很多: TXT,CSV,XLS,SQL等格式,所以,在此总结一下,省的总是百度查询. 一 导出 1) 常用的方式就是使用现成的工具例如 ...
- 熟悉pyspider的装饰器
熟悉pyspider的装饰器取经地点:https://segmentfault.com/a/1190000002477863 @config(age=10 * 24 * 60 * 60) 在这表示我们 ...
- react初入门
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java面试题2019
面向对象的特征有哪些方面? 原来学的时候说是三种特征,即封装.继承和多态. 现在一般说面向对象有四大特性,即抽象.封装.继承和多态. 1.抽象:将同类对象的共同特征提取出来构造类. 2.封装:将数据隐 ...