题目大意

  给你一棵树,有\(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】旅游 树剖的更多相关文章

  1. BZOJ3999:[TJOI2015]旅游(树链剖分)

    Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...

  2. BZOJ3999 [TJOI2015]旅游 【树剖 + 线段树】

    题目 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会选择从A城市买入再 ...

  3. P1505 [国家集训队]旅游[树剖]

    题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...

  4. 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)

    传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...

  5. BZOJ3999 [TJOI2015]旅游

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

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

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

  7. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  8. BZOJ2157 旅游 【树剖 或 LCT】

    题目 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径. ...

  9. luoguP1505旅游(处理边权的树剖)

    /* luogu1505 非常简单的处理边权的树剖题. 在树上将一条边定向,把这条边的权值赋给这条边的出点 树剖的时候不计算lca权值即可 */ #include<bits/stdc++.h&g ...

随机推荐

  1. 配置linux-Fedora系统下iptables防火墙

    参考地址:https://blog.csdn.net/zhangjingyi111/article/details/78902820 本篇文章为实验课过程记录,较为简略. 1.查看系统是否安装ipta ...

  2. 最短路DAG

    边权皆为正时,有最短路DAG. 最短路DAG代表了从原点到每个点的所有最短路. 最短路树个数=最短路DAG生成树个数.用DAG生成树计数即可.复杂度\(O(n+m)\).

  3. 三次握手复习TCP

    临近下班,突然想起三次握手的概念有点模糊. 大学时候的<计算机网络>是英语版的,那时候学习迷迷糊糊的.大概记得一个模型罢了. 幸好,大学基本所有的书都卖了,就是计算机网络没卖.待会回去看看 ...

  4. socket流程

  5. 文本文档中各字母出现次数汇总(java)

    package 字母频率统计; import java.io.*; public class Inputfile { public static void main(String args[]) { ...

  6. mysql_建表

    建表 某字段多个默认值 创建表时,对多选多的字段设置两个以上的默认值时,两个默认值之间用逗号','隔开,不能加空格. create table student2( id int not null, n ...

  7. rest-framework总结

    1. CBV: pass 2 .APIView class BookView(APIView):pass url(r'^books/$', views.BookView.as_view(),name= ...

  8. CLOUD设置过滤方案不共享

    1.打开BOS,找到应用框架-动态表单-过滤方案另存 2.找到共享给他人,把可见性全部去掉

  9. CLOUD SQL跟踪

    CLOUD会自动在后台执行一些sql语句,所以追踪起来比较麻烦,需要加入一些过滤条件. 比如关键的CLIENTPROCESSID,加入后 ,就能过滤是哪个客户度执行的数据. 过滤数据.

  10. web项目中的监听器,过滤器以及自定义servlet的执行顺序

    可以看到web容器一启动就会实例化监听器的contextInitialized(ServletContextEvent event)方法,然后是过滤器的init()方法,最后在用户访问web应用的 时 ...