【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 ...
随机推荐
- H5 标签选择器
08-标签选择器 我是段落 我是段落 我是段落 我是段落 我是段落 我是标题 <!DOCTYPE html> <html lang="en"> <he ...
- Python常用内建方法:__init__,__new__,__class__的理解
python中所有类都是继承自object, 而object提供了很多原始的内建属性和方法,所以用户自定义的类在Python中也会继承这些内建属性.可以使用dir()函数可以查看,虽然python提供 ...
- duxing201606的原味鸡树
链接 [http://murphyc.fun/problem/4011] 题意 描述 众所周知,duxing哥非常喜欢原味鸡.众所周知,原味鸡是长在原味鸡树上的. duxing哥因为是水产巨子,所以就 ...
- Integer的NPE问题
- Debian搭建WordPress
环境配置 可以使用apt-get快速安装mysql,php5:我是用源码手动安装apache服务器的.安装完mysql后,最好将字符编码设置为utf8的. 接下来就是mysql,apache,php5 ...
- CentOS 6.5 手动rpm包安装gcc、g++
摘自:https://blog.csdn.net/lichen_net/article/details/70211204 mount CentOS的安装光盘,然后先后安装 rpm -ivh ppl-0 ...
- pycharm异常问题之Unable to save settings: Failed to save settings. Please restart PyCharm
pycharm异常之Unable to save settings: Failed to save settings. Please restart PyCharm 今天一不小心将电脑关了,但是关机之 ...
- vsconsole
一.安装 npm install vconsole 二. if (process.env.NODE_ENV === `development`) { const { logger } = requir ...
- composer更改源为国际
composer config -g repo.packagist composer https://repo.packagist.org
- 安装openssl
此方法安装原因: 由于我用是非企业版 redhat 没有注册 有很多的yum 不能安装 openssl是在其中. 开始安装: 1.虚拟机挂载ios 镜像文件 2.进入终端 cd /media/RH ...