题解 洛谷 P4695 【[PA2017]Banany】
考虑用动态点分治来解决像本题这样带修的树上路径问题。
首先对原树进行点分治,建出点分树,在点分树每个节点上用动态开点线段树来维护以该节点为起点,到其点分树子树中每个节点的利润。
查询时只需在点分树上当前所在节点往上跳父亲,在其到点分树根节点的链上的每个节点的线段树上查询。跳到一个节点时,在线段树上查询除了当前节点的利润最大值,同时加上其到当前节点的花费。
修改点权只需在点分树上往上跳父亲,在线段树上单点修改即可。
考虑边权的修改影响的是当前根所对应的一个子树,对于边权的修改,从其两个端点在点分树上深度更大,即点分治递归层数更深的点开始往上跳父亲,每次修改在原树上以当前节点为根,深度更浅的那个端点。
点分树上每个节点的线段树在维护时以节点的 \(dfs\) 序为下标,修改子树信息只需在线段树上区间修改即可。
\(code:\)
#include<bits/stdc++.h>
#define maxn 100010
#define maxm 200010
#define maxt 3500010
#define inf 1000000000000000
#define mid ((l+r)>>1)
#define mk make_pair
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,q,tree_cnt,dfn_cnt,tot,root,pos=1;
int fa[maxn],ma[maxn],siz[maxn],num[maxn],d[maxn];
int rt[maxn],ls[maxt],rs[maxt],in[20][maxn],out[20][maxn];
ll v[maxn],tag[maxt];
bool vis[maxn];
map<pair<int,int>,ll> w;
struct edge
{
int to,nxt;
ll v;
}e[maxm];
int head[maxn],edge_cnt;
void add(int from,int to,ll val)
{
e[++edge_cnt]=(edge){to,head[from],val};
head[from]=edge_cnt;
}
struct node
{
ll val;
int id;
}t[maxt];
bool operator <(const node &a,const node &b)
{
if(a.val==b.val) return a.id>b.id;
return a.val<b.val;
}
void pushtag(int cur,ll v)
{
t[cur].val+=v,tag[cur]=v;
}
void pushdown(int cur)
{
if(!tag[cur]) return;
pushtag(ls[cur],tag[cur]),pushtag(rs[cur],tag[cur]),tag[cur]=0;
}
void insert(int l,int r,int pos,ll v,int id,int &cur)
{
if(!cur) cur=++tree_cnt;
if(l==r)
{
t[cur]=(node){v,id};
return;
}
if(pos<=mid) insert(l,mid,pos,v,id,ls[cur]);
else insert(mid+1,r,pos,v,id,rs[cur]);
t[cur]=max(t[ls[cur]],t[rs[cur]]);
}
void modify(int L,int R,int l,int r,ll v,int &cur)
{
if(!cur) cur=++tree_cnt;
if(L<=l&&R>=r)
{
pushtag(cur,v);
return;
}
pushdown(cur);
if(L<=mid) modify(L,R,l,mid,v,ls[cur]);
if(R>mid) modify(L,R,mid+1,r,v,rs[cur]);
t[cur]=max(t[ls[cur]],t[rs[cur]]);
}
node query(int L,int R,int l,int r,int cur)
{
if(L>R||!cur) return (node){-inf,0};
if(L<=l&&R>=r) return t[cur];
pushdown(cur);
if(R<=mid) return query(L,R,l,mid,ls[cur]);
if(L>mid) return query(L,R,mid+1,r,rs[cur]);
return max(query(L,R,l,mid,ls[cur]),query(L,R,mid+1,r,rs[cur]));
}
void dfs_root(int x,int fath)
{
siz[x]=1,ma[x]=0;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]||y==fath) continue;
dfs_root(y,x),siz[x]+=siz[y],ma[x]=max(ma[x],siz[y]);
}
ma[x]=max(ma[x],tot-siz[x]);
if(ma[x]<ma[root]) root=x;
}
void dfs_dis(int x,int fath,ll dis,int id)
{
in[d[id]][x]=++dfn_cnt,insert(1,num[id],dfn_cnt,v[x]-dis,x,rt[id]);
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]||y==fath) continue;
dfs_dis(y,x,dis+e[i].v,id);
}
out[d[id]][x]=dfn_cnt;
}
void solve(int x,int depth)
{
int now=tot;
d[x]=depth,vis[x]=true,num[x]=now,dfn_cnt=0,dfs_dis(x,0,0,x);
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]) continue;
root=0,tot=siz[y];
if(siz[y]>siz[x]) tot=now-siz[x];
dfs_root(y,x),fa[root]=x,solve(root,depth+1);
}
}
int main()
{
read(n),read(q);
for(int i=1;i<=n;++i) read(v[i]);
for(int i=1;i<n;++i)
{
int x,y;
ll v;
read(x),read(y),read(v);
add(x,y,v),add(y,x,v);
if(x>y) swap(x,y);
w[mk(x,y)]=v;
}
tot=ma[0]=n,dfs_root(1,0),solve(root,1);
while(q--)
{
int opt,x,y,p;
ll val,t;
node ans=(node){-inf,0};
read(opt);
if(opt==1)
{
read(x),read(val);
for(int i=x;i;i=fa[i])
modify(in[d[i]][x],in[d[i]][x],1,num[i],val-v[x],rt[i]);
v[x]=val;
}
else
{
read(x),read(y),read(val);
if(x>y) swap(x,y);
t=w[mk(x,y)]-val,w[mk(x,y)]=val;
if(d[x]<d[y]) p=x;
else p=y;
while(p)
{
if(in[d[p]][x]>in[d[p]][y]) modify(in[d[p]][x],out[d[p]][x],1,num[p],t,rt[p]);
else modify(in[d[p]][y],out[d[p]][y],1,num[p],t,rt[p]);
p=fa[p];
}
}
for(int i=pos;i;i=fa[i])
{
node now=max(query(1,in[d[i]][pos]-1,1,num[i],rt[i]),query(in[d[i]][pos]+1,num[i],1,num[i],rt[i]));
now.val+=query(in[d[i]][pos],in[d[i]][pos],1,num[i],rt[i]).val-v[pos],ans=max(ans,now);
}
printf("%d ",pos=ans.id);
}
return 0;
}
题解 洛谷 P4695 【[PA2017]Banany】的更多相关文章
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解-洛谷P5217 贫穷
洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...
- 题解 洛谷 P2010 【回文日期】
By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...
- 题解 洛谷P2158 【[SDOI2008]仪仗队】
本文搬自本人洛谷博客 题目 本文进行了一定的更新 优化了 Markdown 中 Latex 语句的运用,加强了可读性 补充了"我们仍不曾知晓得 消失的 性质5 ",加强了推导的严谨 ...
随机推荐
- mysql性能优化总结(MySql避免重复插入记录的几种方法)
如果我们创建了(area, age,salary)的复合索引,那么其实相当于创建了:(area,age,salary),(area,age).(area)三个索引,这被称为最佳左前缀特性.因此我们在创 ...
- 蒲公英 · JELLY技术周刊 Vol.12 尤雨溪新作 Vite, 你会支持么?
「蒲公英」期刊,每周更新,我们专注于挖掘「基础技术.工程化.跨端框架技术.图形编程.服务端开发.桌面开发.人工智能」等多个大方向的业界热点,并加以专业的解读:不仅如此,我们还精选凹凸技术文章,向大家呈 ...
- SpringBoot--异常统一处理
先上代码,不捕获异常和手动捕获异常处理: @GetMapping("/error1") public String error1() { int i = 10 / 0; retur ...
- 集成Swagger在线调试
SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...
- (私人收藏)SQLite 全面手册以及教程
SQLite 全面手册以及教程 https://pan.baidu.com/s/1VKzCWjF79fAiOLjAlx-3zwnfkp SQLite 全面手册以及教程 SQLite 简介 SQLite ...
- Spring Boot中的事务是如何实现的
本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: Spring Boot中的事务是如何实现的 1. 概述 一直在用SpringBoot中的@Transactional来做事 ...
- JavaScript之原型模式
JavaScript中有这样的一个概念,对象. 有不少人觉得Java这么语言才是面向对象的语言,JavaScript哪里面向对象了. 其实说JavaScript面向对象还不如说JavaScript基于 ...
- 移动端H5页面_input获取焦点时,虚拟键盘挡住input输入框解决方法
在移动端h5开发的时候,发现如果input在页面底部,当触发input焦点的时候会弹出系统虚拟键盘,虚拟键盘会遮挡input输入框.这会很影响用户体验,于是在网上找到了如下的解决办法: 方法一:使用w ...
- Blazor带我重玩前端(三)
写在前面 需要升级VS2019以及.NET Core到最新版(具体的最低支持,我已经忘了,总是越新支持的就越好),以更好的支持自己开发Blazor项目. WebAssembly 搜索Blazor模板 ...
- element-ui自定义table表头,修改标题样式、添加tooltip及 :render-header使用简介
修改列标题样式1.在列标题后面加一个图标. 以element-ui官方文档一个table表格为例,我们在地址的后面加一个定位标志的图标,代码如下: <template> <el-ta ...