【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 ...
随机推荐
- Flask入门的第一个项目进阶版
前言: 此次版本增加[一对多]数据库关系和动态路由设置. 一.数据库设计 environments表与variable1表的关系为:一对多.variable1.env_id设置为外键,与environ ...
- Contest1692 - 2019寒假集训第三十一场 UPC 11075 Problem D 小P的国际象棋
非常简单的单点修改+区间加+区间查询.我用的是最近刚学的区间修改版本树状数组. 直接维护即可,注意修改后的单点值已经不是a[i],或者b[i],要通过区间查询求单点.不然是错的. 区间修改版本树状数 ...
- matplotlib 入门之Sample plots in Matplotlib
文章目录 Line Plot One figure, a set of subplots Image 展示图片 展示二元正态分布 A sample image Interpolating images ...
- Open Live Writer安装教程
配置步骤: 1.在菜单中选择"工具">"帐户",出现下面的画面: 2.点击"添加按钮",在出现的窗口中选择"其他日志服务&q ...
- JS典记
var href = ""; //遍历a标签 $ ( "a"). each (function () { href = ...
- Java面试题详解三:比较器
一,Comparable和Comparator1.Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较.Comparable接口中只有一 ...
- 解决mysql1336
1.mysql字符集与插入数据字符集不匹配 USE 数据库名称SHOW VARIABLES LIKE 'character%'SET character_set_server=utf8;SET cha ...
- 便捷的ajax请求
为什么要做这个呢?如果后端给的数据不单有JSON字符串,还有对象呢?这个时候我们就要每个都处理(JSON.parse).万一后端又改了,所有都是对象呢?如此一来我们就需要对我们的ajax进行封装. 这 ...
- Windows 禁止 chrome 自动更新的方法
来源: https://www.cnblogs.com/zhouwanqiu/p/9329134.html 公司进行兼容性测试 需要chrome的浏览器版本, 但是 公司网络抽风 偶尔 总能是升级到最 ...
- Vue2.0 子组件和父组件之间的传值
Vue是一个轻量级的渐进式框架,对于它的一些特性和优点在此就不做赘述,本篇文章主要来探讨一下Vue子父组件通信的问题 首先我们先搭好开发环境,我们首先得装好git和npm这两个工具(如果有不清楚的同学 ...