【XSY1294】sub 树链剖分
题目描述
给你一棵\(n\)个点的无根树,节点\(i\)有权值\(v_i\)。现在有\(m\)次操作,操作有如下两种:
\(1~x~y\):把\(v_x\)改成\(y\)。
\(2\):选择一个连通块(也可以不选择),使得点权和最大。输出这个点权和。
\(n,m\leq {10}^5,|v_i|,|y|\leq 1000\)
题解
考虑暴力,\(dp_x=v_x+\sum_{y\text{是}x\text{的儿子}}\max(dp_y,0)\)
还记得如果是一条链的问题要怎么做吗?没错,就是线段树。每个区间维护四个信息:
sum表示整个区间的权值和
ls表示以从左边界往右的连续段最大权值和
rs表示以从右边界往左的连续段最大权值和
s表示整个区间中连续段最大权值和
现在这是一棵树,也可以用类似的方法处理。
对于一条重链,每个点的权值就是这个点的\(v\)值加上轻儿子的\(dp\)值。那么这条链的答案就是线段树对应区间的连续段最大权值和。

修改权值的时候,这条链对这条链顶部的轻链上方那个节点的贡献就是修改后从最上面往下的答案\(-\)修改前从最上面往下的答案。
但是线段树上一个区间在原树上不一定是联通的。我们可以在两条不同的重链之间加一个点,权值为\(-\infty\)。这样所有的答案就不会跨过这个不存在的点了。
时间复杂度:\(O(m\log^2 n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<list>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll dp[200010];
int c[200010];
namespace seg
{
struct pp
{
ll ls,rs,s,sum;
};
pp operator +(pp a,pp b)
{
pp c;
c.sum=a.sum+b.sum;
c.ls=max(a.ls,a.sum+b.ls);
c.rs=max(b.rs,b.sum+a.rs);
c.s=max(max(a.s,b.s),a.rs+b.ls);
return c;
}
pp s[500010];
int ls[500010];
int rs[500010];
int cnt;
int build(int l,int r)
{
int p=++cnt;
if(l==r)
{
s[p].sum=c[l];
s[p].ls=s[p].rs=s[p].s=max(0ll,s[p].sum);
return p;
}
int mid=(l+r)>>1;
ls[p]=build(l,mid);
rs[p]=build(mid+1,r);
s[p]=s[ls[p]]+s[rs[p]];
return p;
}
void change(int p,int x,ll v,int L,int R)
{
if(L==R)
{
s[p].sum+=v;
s[p].ls=s[p].rs=s[p].s=max(0ll,s[p].sum);
return;
}
int mid=(L+R)>>1;
if(x<=mid)
change(ls[p],x,v,L,mid);
else
change(rs[p],x,v,mid+1,R);
s[p]=s[ls[p]]+s[rs[p]];
}
pp query(int p,int l,int r,int L,int R)
{
if(l<=L&&r>=R)
return s[p];
int mid=(L+R)>>1;
if(r<=mid)
return query(ls[p],l,r,L,mid);
if(l>mid)
return query(rs[p],l,r,mid+1,R);
return query(ls[p],l,r,L,mid)+query(rs[p],l,r,mid+1,R);
}
};
struct p
{
int s,ms,f,d,t,w;
};
int inf=0x7fffffff;
p a[100010];
list<int> l[100010];
int v[100010];
int ti;
void dfs(int x,int f,int d)
{
a[x].f=f;
a[x].d=d;
a[x].s=1;
dp[x]=v[x];
int sz=0;
for(auto v:l[x])
if(v!=f)
{
dfs(v,x,d+1);
dp[x]+=max(dp[v],0ll);
a[x].s+=a[v].s;
if(a[v].s>sz)
{
sz=a[v].s;
a[x].ms=v;
}
}
}
void dfs2(int x,int t)
{
a[x].t=t;
a[x].w=++ti;
if(a[x].ms)
{
dp[x]-=max(dp[a[x].ms],0ll);
dfs2(a[x].ms,t);
for(auto v:l[x])
if(v!=a[x].f&&v!=a[x].ms)
{
c[++ti]=-inf;
dfs2(v,v);
}
}
c[a[x].w]=dp[x];
}
void change(int x,int y)
{
y-=v[x];
v[x]+=y;
for(;x;x=a[a[x].t].f)
{
int t=a[a[x].t].w;
int v1=seg::query(1,t,ti,1,ti).ls;
seg::change(1,a[x].w,y,1,ti);
int v2=seg::query(1,t,ti,1,ti).ls;
y=v2-v1;
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
seg::cnt=0;
int n,m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
scanf("%d",&v[i]);
int x,y;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
l[x].push_back(y);
l[y].push_back(x);
}
ti=0;
dfs(1,0,1);
dfs2(1,1);
seg::build(1,ti);
for(i=1;i<=m;i++)
{
scanf("%d",&x);
if(x==1)
{
scanf("%d%d",&x,&y);
change(x,y);
}
else
printf("%lld\n",seg::s[1].s);
}
return 0;
}
【XSY1294】sub 树链剖分的更多相关文章
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
- 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...
- 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...
- bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...
- bzoj3631树链剖分
虽然是水题1A的感觉太爽了O(∩_∩)O~ 题意相当于n-1次树上路径上每个点权值+1,最后问每个点的权值 本来想写线段树,写好了change打算框架打完了再来补,结果打完发现只是区间加和单点查 前缀 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
随机推荐
- Mysql权限操作、用户管理、密码操作
Mysql的权限 mysql中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表. mysql权限表的验证过程为: 先从user表中的Host,Use ...
- 1003: [ZJOI2006]物流运输 = DP+SBFA
题意就是告诉你有n个点,e条边,m天,每天都会从起点到终点走一次最短路,但是有些点在某些时间段是不可走的,因此在某些天需要改变路径,每次改变路径的成本是K,总成本=n天运输路线长度之和+K*改变运输路 ...
- 【评分】BETA 版冲刺前准备
[评分]BETA 版冲刺前准备 总结 本次作业较为简洁,计1分,按时提交计分,不提交不计分. 详细得分 组 短学号 名 分数 Boy Next Door 114 显东 1 Boy Next Door ...
- NFV论文集(三)综述
一 文章名称:Dependability of the NFV Orchestrator: State of the Art and Research Challenges 发表时间:2018 期刊来 ...
- scrapy框架爬取妹子图片
首先,建立一个项目#可在github账户下载完整代码:https://github.com/connordb/scrapy-jiandan2 scrapy startproject jiandan2 ...
- js判断手机机型,然后进行相对应的操作
我们通过浏览器内置的userAgent来判断手机机型. 具体代码如下: var u = navigator.userAgent, app = navigator.appVersion; if(/App ...
- java代理:静态代理和动态代理
一.Java中有一个设计模式是代理模式 代理模式是常用的Java设计模式,特征是代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类 ...
- Linux 下面 Sqlserver 2017 的简单安装
1. 公司网络太烂 yum 在线安装失败 2. 解决方法 找微软的官网 百度网盘 离线下载rpm包. https://packages.microsoft.com/rhel/7/mssql-serve ...
- Day 4-2 time & datetime模块
time模块. import time time.time() #输出: 1523195163.140625 time.localtime() # 获取的是操作系统的时间,可以添加一个时间戳参数 # ...
- 谈谈B-树和B+树及其应用
待更!!! B-树和B+树的应用:数据搜索和数据库索引 B+/-Tree原理及mysql的索引分析 从B树.B+树.B*树谈到R 树 B树.B-树.B+树.B*树