热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【bzoj3730:震波】【动态树分治】

题意给出一棵树,点有点权,每次询问距离一个点不超过kkk的点的点权和,或者修改一个点的点权,强制在线。n≤100000n\

题意

给出一棵树,点有点权,每次询问距离一个点不超过kkk的点的点权和,或者修改一个点的点权,强制在线。
n≤100000n\le100000n100000


分析

把点分树建出来,然后对每个分治中心用树状数组维护到该点距离为定值的点权和,以及到他点分树上父亲距离为定值的点权和。查询的时候每次沿着父亲往上跳,在计算当前点贡献时需要减去上一个点所在子树的贡献。
时间复杂度O(nlog⁡2n)O(n\log^2n)O(nlog2n)


代码

#include
#include
#include
#include
#include
#includeconst int N=100005;int n,m,cnt,last[N],dep[N],dfn[N],top,rmq[N*2][20],lg[N*2],bin[20],c1[20][N],c2[20][N],fa[N],rt,sum,mx[N],a[N],beg[N],size[N],dd[N],tot[20],end[N];
bool vis[N];
struct edge{int to,next;}e[N*2];void addedge(int u,int v)
{e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}void dfs(int x,int fa)
{rmq[++top][0]=x;dep[x]=dep[fa]+1;dfn[x]=top;for (int i=last[x];i;i=e[i].next)if (e[i].to!=fa) dfs(e[i].to,x),rmq[++top][0]=x;
}void get_rmq()
{for (int i&#61;1;i<&#61;top;i&#43;&#43;) lg[i]&#61;log(i)/log(2);bin[0]&#61;1;for (int i&#61;1;i<&#61;lg[top];i&#43;&#43;) bin[i]&#61;bin[i-1]*2;for (int j&#61;1;j<&#61;lg[top];j&#43;&#43;)for (int i&#61;1;i&#43;bin[j]-1<&#61;top;i&#43;&#43;)rmq[i][j]&#61;dep[rmq[i][j-1]]<dep[rmq[i&#43;bin[j-1]][j-1]]?rmq[i][j-1]:rmq[i&#43;bin[j-1]][j-1];
}int get_dis(int x,int y)
{int l&#61;std::min(dfn[x],dfn[y]),r&#61;std::max(dfn[x],dfn[y]),w&#61;lg[r-l&#43;1];return dep[x]&#43;dep[y]-2*std::min(dep[rmq[l][w]],dep[rmq[r-bin[w]&#43;1][w]]);
}void get_root(int x,int fa)
{size[x]&#61;1;mx[x]&#61;0;for (int i&#61;last[x];i;i&#61;e[i].next){if (e[i].to&#61;&#61;fa||vis[e[i].to]) continue;get_root(e[i].to,x);size[x]&#43;&#61;size[e[i].to];mx[x]&#61;std::max(mx[x],size[e[i].to]);}mx[x]&#61;std::max(mx[x],sum-size[x]);if (!rt||mx[x]<mx[rt]) rt&#61;x;
}void ins1(int d,int x,int y)
{while (x<&#61;n) c1[d][x]&#43;&#61;y,x&#43;&#61;x&(-x);
}void ins2(int d,int x,int y)
{while (x<&#61;n) c2[d][x]&#43;&#61;y,x&#43;&#61;x&(-x);
}int query1(int d,int x)
{if (!d) return 0;int ans&#61;0;while (x) ans&#43;&#61;c1[d][x],x-&#61;x&(-x);return ans;
}int query2(int d,int x)
{if (!d) return 0;int ans&#61;0;while (x) ans&#43;&#61;c2[d][x],x-&#61;x&(-x);return ans;
}void pre(int x,int fa,int p1,int p2)
{ins1(dd[p1],beg[p1]&#43;get_dis(p1,x),a[x]);if (p2) ins2(dd[p1],beg[p1]&#43;get_dis(p2,x)-1,a[x]);tot[dd[p1]]&#43;&#43;;size[x]&#61;1;for (int i&#61;last[x];i;i&#61;e[i].next)if (e[i].to!&#61;fa&&!vis[e[i].to]) pre(e[i].to,x,p1,p2),size[x]&#43;&#61;size[e[i].to];
}void solve(int x)
{vis[x]&#61;1;dd[x]&#61;dd[fa[x]]&#43;1;beg[x]&#61;tot[dd[x]]&#43;1;pre(x,0,x,fa[x]);end[x]&#61;tot[dd[x]];for (int i&#61;last[x];i;i&#61;e[i].next)if (!vis[e[i].to]){rt&#61;0;sum&#61;size[e[i].to];get_root(e[i].to,x);fa[rt]&#61;x;solve(rt);}
}int query(int x,int y)
{int ans&#61;0,ls&#61;0,now&#61;x;while (now){int d&#61;y-get_dis(x,now);if (d>&#61;0) ans&#43;&#61;query1(dd[now],std::min(beg[now]&#43;d,end[now]))-query1(dd[now],beg[now]-1);if (d>&#61;0) ans-&#61;query2(dd[ls],std::min(beg[ls]&#43;d-1,end[ls]))-query2(dd[ls],beg[ls]-1);ls&#61;now;now&#61;fa[now];}return ans;
}void modify(int x,int y)
{int del&#61;y-a[x],now&#61;x;a[x]&#61;y;while (now){ins1(dd[now],beg[now]&#43;get_dis(now,x),del);if (fa[now]) ins2(dd[now],beg[now]&#43;get_dis(fa[now],x)-1,del);now&#61;fa[now];}
}int main()
{scanf("%d%d",&n,&m);for (int i&#61;1;i<&#61;n;i&#43;&#43;) scanf("%d",&a[i]);for (int i&#61;1;i<n;i&#43;&#43;){int x,y;scanf("%d%d",&x,&y);addedge(x,y);}dfs(1,0);get_rmq();rt&#61;0;sum&#61;n;get_root(1,0);solve(rt);int ans&#61;0;while (m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);x^&#61;ans;y^&#61;ans;if (!op) printf("%d\n",ans&#61;query(x,y));else modify(x,y);}return 0;
}

推荐阅读
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • JSOI2010 蔬菜庆典:树结构中的无限大权值问题
    本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ... [详细]
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • 在进行QT交叉编译时,可能会遇到与目标架构不匹配的宏定义问题。例如,当为ARM或MIPS架构编译时,需要确保使用正确的宏(如QT_ARCH_ARM或QT_ARCH_MIPS),而不是默认的QT_ARCH_I386。本文将详细介绍如何正确配置编译环境以避免此类错误。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。 ... [详细]
  • Qt QTableView 内嵌控件的实现方法
    本文详细介绍了在 Qt QTableView 中嵌入控件的多种方法,包括使用 QItemDelegate、setIndexWidget 和 setIndexWidget 结合布局管理器。每种方法都有其适用场景和优缺点。 ... [详细]
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • JavaScript 基础语法指南
    本文详细介绍了 JavaScript 的基础语法,包括变量、数据类型、运算符、语句和函数等内容,旨在为初学者提供全面的入门指导。 ... [详细]
  • 题目描述:给定一个N*M的网格,初始时网格中有k个芯片,每个芯片的位置已知。玩家可以在每一步操作中将所有芯片沿同一方向移动一格。如果芯片到达边界,则保持不动。目标是通过一系列操作,使每个芯片依次访问指定的目标位置。 ... [详细]
  • 本题要求实现一个函数,用于检查给定的字符串是否为回文。回文是指正向和反向读取都相同的字符串。例如,“XYZYX”和“xyzzyx”都是回文。 ... [详细]
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 历经三十年的开发,Mathematica 已成为技术计算领域的标杆,为全球的技术创新者、教育工作者、学生及其他用户提供了一个领先的计算平台。最新版本 Mathematica 12.3.1 增加了多项核心语言、数学计算、可视化和图形处理的新功能。 ... [详细]
author-avatar
JIE9118_755
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有