点分树

news/2025/11/16 19:54:51/文章来源:https://www.cnblogs.com/allforgod/p/19228809

事实上比较朴素。

P6329 【模板】点分树 | 震波

大致思路是将点分治的那个过程建成一棵树。每一层的重心和下一层的中心连边。

这棵树有两个重要性质:树高保证为 \(\log n\),任意两点的 lca 一定在这两个点的路径上。

于是我们可以在这棵树上做一些类似于 DP 的事情去统计路径的问题。由于保证了树高,因此我们可以有一些很暴力的操作,比如跳根链和暴力存子树内的每一个点之类的。

对于原题,我们先建出点分树,然后对每一个点开一个动态开点线段树维护点分树上子树内的所有点到当前点距离的权值。
例如说,我们对于询问距离 \(u\) 小于等于 \(x\) 的节点的权值和,我们就去枚举 \(v\) 表示 \(u\) 到点分树上根链的所有点。

于是就是询问 \(v\) 子树中到 \(u\) 距离不超过 \(x-dis(v,u)\) 的点的个数,这个过程相当于将 \(v\) 当作 lca 然后统计经过这个 lca 的点对的贡献。但是注意如果 \(v\) 是 lca 那么另一个点不能在 \(u\) 所在的那个子树中,因此要去掉在 \(u\) 那个方向的子树的贡献。我们再开一颗线段树将这个东西挂在对应方向的那个子树上,也就是每个点维护子树内每个点到父亲的距离的权值。
然后查询和修改的时候就暴力跳根链改对应线段树即可。

code

注意到需要求两点间距离,因此需要调用巨量次 lca,因此建议写一个 \(O(1)\) 查询的东西。普通的树上倍增太慢了。

自认为比较好看。

点击查看代码
#include<bits/stdc++.h>
bool Mbe;
using namespace std;
#define ll long long
//namespace FIO{
//	template<typename P>
//	inline void read(P &x){P res=0,f=1;char ch=getchar();while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}x=res*f;}
//	template<typename Ty,typename ...Args>
//	inline void read(Ty &x,Args &...args) {read(x);read(args...);}
//	inline void write(ll x) {if(x<0ll)putchar('-'),x=-x;static int sta[35];int top = 0;do {sta[top++] = x % 10ll, x /= 10ll;} while (x);while (top) putchar(sta[--top] + 48);}
//}
//using FIO::read;using FIO::write;
const int N=1e5+7;
int n,m,val[N],zx,siz[N],mxsiz[N],vis[N],F[N];
vector<int> q[N],p[N];
void Max(int &x,const int &y){x=max(x,y);}
void Min(int &x,const int &y){x=min(x,y);}
namespace LCA{int dfncnt=0,dfn[N],loc[N],f[N][17],Lg[N],dep[N];void dfs(int u,int fa){dfn[u]=++dfncnt,loc[dfn[u]]=u;f[dfn[u]][0]=dfn[fa];dep[u]=dep[fa]+1;for(int i=1;(1<<i)+1<=dfn[u];i++)f[dfn[u]][i]=min(f[dfn[u]][i-1],f[dfn[u]-(1<<(i-1))][i-1]);for(int v:q[u]){if(v==fa)continue;dfs(v,u);}}void init(){Lg[0]=-1;for(int i=1;i<=n;i++)Lg[i]=Lg[i/2]+1;dfs(1,0);}int get(int l,int r){int k=Lg[r-l+1];return min(f[r][k],f[l+(1<<k)-1][k]);}int lca(int x,int y){if(x==y)return x;if(dfn[x]>dfn[y])swap(x,y);return loc[get(dfn[x]+1,dfn[y])];}int getdis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
}
using LCA::getdis;using LCA::lca;
void findrt(int u,int fa,int sumsiz){siz[u]=1;mxsiz[u]=0;for(int v:q[u]){if(v==fa||vis[v])continue;findrt(v,u,sumsiz);Max(mxsiz[u],siz[v]);siz[u]+=siz[v];}Max(mxsiz[u],sumsiz-siz[u]);if(mxsiz[u]<mxsiz[zx])zx=u;
}
void build_tr(int u,int fa){if(fa)p[fa].push_back(u),p[u].push_back(fa);vis[u]=1;for(int v:q[u]){if(vis[v])continue;mxsiz[0]=n,zx=0;findrt(v,u,siz[v]);build_tr(zx,u);}
}
struct sgt{int idcnt=0,rt[N],tr[N<<6],ls[N<<6],rs[N<<6];#define mid ((l+r)>>1)void push_up(int u){tr[u]=tr[ls[u]]+tr[rs[u]];}void modify(int &u,int l,int r,int x,int w){if(!u)u=++idcnt;if(l==r){tr[u]+=w;return;}x<=mid?modify(ls[u],l,mid,x,w):modify(rs[u],mid+1,r,x,w);push_up(u);}int query(int u,int l,int r,int ql,int qr){if(!u)return 0;if(ql<=l&&r<=qr)return tr[u];int res=0;if(ql<=mid)res+=query(ls[u],l,mid,ql,qr);if(qr>mid)res+=query(rs[u],mid+1,r,ql,qr);return res;}
}t1,t2;
vector<int>id[N];
void dfs(int u,int fa){id[u].push_back(u);F[u]=fa;for(int v:p[u]){if(v==fa)continue;dfs(v,u);for(int w:id[v])id[u].push_back(w);}for(int v:id[u]){t1.modify(t1.rt[u],0,n,getdis(u,v),val[v]);if(fa)t2.modify(t2.rt[u],0,n,getdis(fa,v),val[v]);}
}
bool Med;
signed main(){  //注意 vis!!!ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);//freopen(".in","r",stdin);//freopen(".out","w",stdout);cin>>n>>m;for(int i=1;i<=n;i++)cin>>val[i];for(int i=1,u,v;i<n;i++)cin>>u>>v,q[u].push_back(v),q[v].push_back(u);LCA::init();mxsiz[0]=n,zx=0;findrt(1,0,n);int RT=zx;  //这个是点分树的真正的根build_tr(zx,0);dfs(RT,0);int lst=0;for(int i=1;i<=m;i++){int op,u,x;cin>>op>>u>>x;u^=lst,x^=lst;if(op==0){int ans=t1.query(t1.rt[u],0,n,0,x),bu=u;while(F[u]){if(getdis(F[u],bu)<=x)ans+=t1.query(t1.rt[F[u]],0,n,0,x-getdis(bu,F[u]))-t2.query(t2.rt[u],0,n,0,x-getdis(bu,F[u]));u=F[u];}cout<<ans<<'\n';lst=ans;}else{int bu=u;while(u){t1.modify(t1.rt[u],0,n,getdis(u,bu),x-val[bu]);if(F[u])t2.modify(t2.rt[u],0,n,getdis(F[u],bu),x-val[bu]);u=F[u];}val[bu]=x;}}cerr<<'\n'<<1e3*clock()/CLOCKS_PER_SEC<<"ms\n";cerr<<'\n'<<fabs(&Med-&Mbe)/1048576.0<<"MB\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/967305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP请求走私漏洞介绍 - 实践

HTTP请求走私漏洞介绍 - 实践2025-11-16 19:46 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important…

20232428 2025-2026-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 (1)从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取信息 (2)尝试获取BBS、论坛、QQ、MSN中某一好友的IP地址,并查询获取该好友所在的具体地理位置 (3)使用nmap开源软件…

xml.etree.ElementTree 完全支持嵌套查找子元素,且有多种简洁实用的方式。

xml.etree.ElementTree 完全支持嵌套查找子元素,且有多种简洁实用的方式。 核心实现方式 1. XPath 路径直接嵌套查找(最常用) 通过 / 分隔层级,直接定位深层子元素,支持精确匹配标签名、属性等。 import xml.etre…

深入解析:Spring MVC 拦截器interceptor

深入解析:Spring MVC 拦截器interceptorpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…

HarmonyOS 5 鸿蒙Context上下文机制与资源管理详解 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

《重生之我成为世界顶级黑客》第八章:未来野望

《重生之我成为世界顶级黑客》第八章:未来野望词穷,暂时没灵感了。龙傲天盯着桌上那个用40积分换来的企鹅玩偶,嘴角泛起一丝苦涩的笑意。这次的经历像一盆冷水,浇醒了他这些天因微小进步而产生的自满。企业的安全防…

打开工作空间时,但未在 DTD/架构中声明

OpenFromFile时,如果路径不存在或者不合法, 将报错,请先检查路径! {"未指定的错误\r\n\r\n使用了元素 {http://schemas.microsoft.com/windows/2005/02/color/WcsCommonProfileTypes}Text,但未在 DTD/架构中…

开源软件的崛起:技术共享与协作创新的新时代 - 详解

开源软件的崛起:技术共享与协作创新的新时代 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&quo…

从 LLM 到 Agentic AI:构建下一代智能平台的全栈路径

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

11.16组会

R语言 应用:统计分析、绘图功能、扩展生态 列表、数组、矩阵、数据框 平均值、最大最小、中位数等 作各种图,质量好

20232418 2025-2026-1 《网络与系统攻防技术》实验五实验报告

20232418 2025-2026-1 《网络与系统攻防技术》实验五实验报告 1.实验内容 1.1通过whois、dig、nslookup等命令查询DNS域名、IP地址的详细信息。 1.2通过资源监视器和在线工具得到IP地址并确定其地理位置。 1.3nmap开源…

Claude Code教程:从零构建AutoPost GPT自动内容生成系统

Claude Code教程:从零构建AutoPost GPT自动内容生成系统AutoPost GPT是一个非常适合Claude Code 的全流程实战项目,它涵盖了从架构设计到模块拆分、从 API 调用到任务调度、从内容生成到自动发布的完整工程链路。如果…

MFC + OpenCV 图像预览显示不全中断问题解除:GDI行填充详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

python多进程 —— multiprocessing.Manager —— 跨主机共享内存的读写

python多进程 —— multiprocessing.Manager —— 跨主机共享内存的读写python多进程 —— multiprocessing.Manager —— 跨主机共享内存的读写示例代码:点击查看代码 import multiprocessingdef f(ns):ns.x.append(…

AT_agc063_e Child to Parent 题解

AT_agc063_e Child to Parent 题解 设 \(c_x\) 表示点 \(x\) 一共执行的操作次数,对于不同的 \(c_x\) 序列最终的 \(A\) 序列是不同的,因此我们对 \(c_x\) 序列计数即可。 容易发现一个 \(c_x\) 合法的充要是 \(0\le…

详细介绍:UVa 11129 An Antiarithmetic Permutation

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

3天掌握OpenHarmony+Python开发:高效适配教程与真实项目案例精讲 - 教程

3天掌握OpenHarmony+Python开发:高效适配教程与真实项目案例精讲 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family:…

飞牛os打开本机usb摄像头

飞牛os打开本机usb摄像头笔记本安装了飞牛os,想打开本机的USB摄像头,参考文章——Linux运维笔记[15]-网页ip摄像头 我用的是第一种办法,有些命令需要修改: 1、安装go并配置环境wget -O go_install.sh https://go.g…

CF 2156E Best Time to Buy and Sell Stock

vp 这场 E, F1 都写爆了被一起逮捕,我是人?直接求解答案似乎并不容易,因为需要考虑的大小关系太多了,于是可以尝试二分转为 01 问题。 于是尝试思考,如何判断答案是否 \(\ge w\)。 这个问题并不具有一些特殊的结构…