静态点分治总结

点分治是世界上最好的算法QwQ

点分治可以解决各种树上的边权点权问题,然后如果你发现这个题好像问的特别玄学,lca,树差都做不了,树上动‘龟’更做不了,只能暴力时,这个题大多数情况就是点分治了

点分治的思路,考虑指定p为根,对于p而言,树上路径分为两类,过p的路径,子树内的路径,显然对于子树内的路径,只要让他继续递归下去就行了,然后我们现在要算的就是经过p的路径

算法过程

一,求出来重心

二,从重心开始跑dfs维护出这一段权值(路径长度等)

三,运行calc计算对ans贡献

四,从子树运行一--三

点分治时间复杂度nlogn,证明被咕了

为什么非得是重心,首先复杂度与最大的子树有关,如果是直接往下搜y时,遇到一个链会退化成$n^2 log n$,若从重心开始搜,保证了子树小于$\frac{n}{2}$

 

 

运行点分治大约有两种思路第一种是暴力计算然后容斥(为什么容斥被咕了),第二种是类似树形背包转移,再加上各种数据结构维护

两种都比较常用容斥特别好打,背包适用广

我们拿几个例题看看点分治的思路

例题

聪聪可可

一颗n(n<=20000)个点的树上,求长度是3的倍数的路径条数。

思路清真,我们统计出来各个子树内路径,最后让他们合并(长度余2与长度余1合并,长度余3于长度余3合并)最终就得到了解,我们维护出每一段路径的余数

类似于

void getdeep(ll x,ll fa){tt[deep[x]%3]++;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;deep[y]=deep[x]+edge[i];getdeep(y,x);}
}
ll calc(ll x,ll val){deep[x]=val;for(ll i=0;i<=2;i++)tt[i]=0;getdeep(x,0);return tt[1]*tt[2]*2+tt[0]*tt[0];
} 
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Inf 1008611555ll
#define A 1000000
ll head[A],nxt[A],ver[A],edge[A],sz[A],vis[A],tt[A],deep[A];
ll size,toot,n,m,mx,ans,tot;
void add(ll x,ll y,ll z){nxt[++tot]=head[x],head[x]=tot,ver[tot]=y,edge[tot]=z;
}
ll gcd(ll x,ll y){if(y==0) return x;return gcd(y,x%y);
}
void gettoot(ll x,ll fa){sz[x]=1;ll num=0;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;gettoot(y,x);sz[x]+=sz[y];num=max(num,sz[y]);}num=max(num,size-sz[x]);if(num<mx) mx=num,toot=x;
}
void getdeep(ll x,ll fa){tt[deep[x]%3]++;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;deep[y]=deep[x]+edge[i];getdeep(y,x);}
}
ll calc(ll x,ll val){deep[x]=val;for(ll i=0;i<=2;i++)tt[i]=0;getdeep(x,0);return tt[1]*tt[2]*2+tt[0]*tt[0];
}
ll solve(ll x){ans+=calc(x,0);
//    printf("x=%lld t1=%lld t2=%lld t0=%lld ans=%lld\n",x,tt[1],tt[2],tt[0],ans);vis[x]=1;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;ans-=calc(y,edge[i]);
//        printf("ans=%lld\n",ans);size=sz[y];mx=Inf;gettoot(y,0);solve(toot);}
}
int main(){scanf("%lld",&n);for(ll i=1;i<n;i++){ll x,y,z;scanf("%lld%lld%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}mx=Inf;size=n;gettoot(1,0);solve(toot);ll g=gcd(ans,n*n);printf("%lld/%lld\n",ans/g,n*n/g);
}
View Code

tree

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

思路清真,我们统计出来子树之间距离然后统计一波排序一波,点对一波就好了

类似于

void getdis(ll x,ll fa){q[++r]=d[x];for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(y==fa||vis[y]) continue;d[y]=d[x]+edge[i];getdis(y,x);}
}
ll calc(ll x,ll val){r=0;d[x]=val;getdis(x,0);ll sum=0;l=1;sort(q+1,q+r+1);while(l<r){if(q[l]+q[r]<=k) sum+=r-l,++l;else --r;}return sum;
}
#include<bits/stdc++.h>
#define ll long long
#define A 1100000
#define Inf 1000000000ll
using namespace std;
ll head[A],nxt[A],ver[A],sz[A],q[A],d[A],sum[A],edge[A];
ll size,toot,mx,n,m,tot=0,ans,k,l,r;
bool vis[A];
void add(ll x,ll y,ll z){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot,edge[tot]=z;
}
void gettoot(ll x,ll fa){sz[x]=1;ll num=0;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(y==fa||vis[y]) continue;gettoot(y,x);sz[x]+=sz[y];num=max(num,sz[y]);}num=max(size-sz[x],num);if(num<mx) mx=num,toot=x;
}
void getdis(ll x,ll fa){q[++r]=d[x];
//    printf("   x=%lld r=%lld\n",x,r);for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(y==fa||vis[y]) continue;d[y]=d[x]+edge[i];getdis(y,x);}
}
ll calc(ll x,ll val){r=0;d[x]=val;getdis(x,0);ll sum=0;l=1;
//    printf("r=%lld l=%lld\n",l,r);sort(q+1,q+r+1);while(l<r){if(q[l]+q[r]<=k) sum+=r-l,++l;else --r;}return sum;
}
ll solve(ll x){ans+=calc(x,0);vis[x]=1;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;ans-=calc(y,edge[i]);size=sz[y];mx=Inf;gettoot(y,0);solve(toot);}
}
int main(){scanf("%lld",&n);for(ll i=1;i<n;i++){ll x,y,z;scanf("%lld%lld%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}scanf("%lld",&k);size=n;mx=Inf;gettoot(1,0);solve(toot);cout<<ans<<endl;
}
View Code

race

路径和为k且路径的边数最少

我们开一个桶,维护出路径和为k时边数最小值,记得清零

 类似这样

void getdiss(ll x,ll fa,ll dp){if(deep[x]<=k)ans=min(ans,dp+cnt[k-deep[x]]);for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;deep[y]=deep[x]+edge[i];getdiss(y,x,dp+1);}
}
void uptoday(ll x,ll fa,ll dp,ll ooo){if(deep[x]<=k)ooo?(cnt[deep[x]]=min(cnt[deep[x]],dp)):cnt[deep[x]]=n;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;uptoday(y,x,dp+1,ooo);}
}
void solve(ll x){vis[x]=1;cnt[0]=0;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;deep[y]=edge[i];getdiss(y,0,1);uptoday(y,0,1,1);}for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(!vis[y])uptoday(y,0,1,0);}for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;mx=Inf;size=sz[y];gettoot(y,0);solve(toot);}
}
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define Inf 1e9
#define A 6100000
ll t[A+10],sz[A],nxt[A],head[A],ver[A],edge[A],cnt[A],deep[A];
ll mx,size,num,k,toot,ans=0,n,tot=0;
bool vis[A];
void add(ll x,ll y,ll z){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot,edge[tot]=z;
}
void gettoot(ll x,ll fa){sz[x]=1;ll num=0;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;gettoot(y,x);sz[x]+=sz[y];num=max(num,sz[y]);}num=max(num,size-sz[x]);if(num<mx) mx=num,toot=x;
}
void getdiss(ll x,ll fa,ll dp){if(deep[x]<=k)ans=min(ans,dp+cnt[k-deep[x]]);for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;deep[y]=deep[x]+edge[i];getdiss(y,x,dp+1);}
}
void uptoday(ll x,ll fa,ll dp,ll ooo){if(deep[x]<=k)ooo?(cnt[deep[x]]=min(cnt[deep[x]],dp)):cnt[deep[x]]=n;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]||y==fa) continue;uptoday(y,x,dp+1,ooo);}
}
void solve(ll x){vis[x]=1;cnt[0]=0;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;deep[y]=edge[i];getdiss(y,0,1);uptoday(y,0,1,1);}for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(!vis[y])uptoday(y,0,1,0);}for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(vis[y]) continue;mx=Inf;size=sz[y];gettoot(y,0);solve(toot);}
}
int main(){cin>>n>>k;ans=n;ll x,y,z;for(ll i=1;i<=n-1;i++){cin>>x>>y>>z;x++,y++;add(x,y,z);add(y,x,z);}mx=Inf;size=n;for(ll i=1;i<=k;i++) cnt[i]=n;gettoot(1,0);solve(toot);if(ans==n)puts("-1");else printf("%d\n",ans);
}
View Code

常见题目

路径和等于或小于等于k的点对(路径条数)。例如tree

路径和为某个数的倍数。没遇到过,但也应该类似于聪聪可可

路径和为k且路径的边数最少。例如race,我们只要开一个桶记录一下路径为k时最小路径

路径和mod M后为某个值。例如聪聪可可

路径上经过不允许点的个数不超过某个值,且路径和最大。例如免费旅行

大多数题开一个桶i,表示距离为i的相关信息,有时我们也可以用一些高级数据结构(例如树状数组)进行一波维护。

 

转载于:https://www.cnblogs.com/znsbc-13/p/11249423.html

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

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

相关文章

html节点上下移动,关于前端:数组元素上下移动

/*** 上、下挪动* param {number} code 下标* param {number} dir 1上移 0下移*/onMove(code, dir) {let moveComm (curIndex, nextIndex) > {let arr this.commodityInfoarr[curIndex] arr.splice(nextIndex, 1, arr[curIndex])[0]return arr}this.commodityInfo.some((…

mybatis插入数据后返回自增主键ID详解

1.场景介绍: ​ 开发过程中我们经常性的会用到许多的中间表,用于数据之间的对应和关联.这个时候我们关联最多的就是ID,我们在一张表中插入数据后级联增加到关联表中.我们熟知的mybatis在插入数据后返回的是插入成功的条数,那么这个时候我们想要得到相应的这条新增数据的ID,该怎…

spring 属性占位符_Spring属性占位符配置器–一些不太明显的选项

spring 属性占位符Spring的PropertySourcesPlaceholderConfigurer用于从XML或Java Config中定义的Spring bean定义外部化属性。 PlaceholderConfigurer支持的一些选项在文档中并不明显&#xff0c;但很有趣&#xff0c;并且可能有用。 首先&#xff0c;以Spring文档中的示例为…

红包雨效果html,js+css实现红包雨效果

//每一个红包都是相对于父元素定位&#xff0c;通过z-index来设置层级let zIndex 1;function bindEvent() {$redPackage.on(click,.js-RedPackageBox,function() {//拿到每个红包的数据const data $(this).data(txt);}}//生成mix-max的随机数function getRandom(min,max) {re…

Delphi下实现全屏快速找图找色 二、矩阵遍历

二、矩阵遍历  矩阵遍历是一个数据结构方面的问题。假设有一个矩阵Matrix&#xff0c;它共有RowCount行&#xff0c;每行有ColCount列&#xff0c;当利用y表示行数&#xff0c;x表示列数&#xff0c;那么利用Matrix[y,x]就可以访问矩阵中的任意元素。假设有一个1010大小的矩阵…

Eclipse MicroProfile:您需要了解的5件事

针对微服务架构优化企业Java Eclipse MicroProfile计划是在JavaOne 2016上发起的&#xff0c;JavaOne是服务器供应商和Java用户组的创意&#xff0c;目的是解决企业Java微服务领域的缺点。 Java EE的发布速度减慢到无法应对Swift发展的微服务趋势的挑战的程度。 MicroProfile通…

html 选择不能重复,人生,就是一次无法重复的选择(深度好文)

作者&#xff1a;彩云追月欧洲著名的政治家托马斯 莫尔说&#xff1a;“在人生中最艰难的是选择”。漫漫人生路&#xff0c;有无数的选择&#xff0c;不同的选择&#xff0c;可能会决定我们不同的人生道路。下面的故事也许对你有所启迪&#xff1a;一天&#xff0c;几个学生问…

用HTML做软件UI用到的的一些技术

做WEB开发的想把网页做成应用程序的界面&#xff0c;开发应用程序的又想把程序界面做得和WEB一样。本文介绍一下用HTML做软件UI用到的的一些技术。 其实HTML UI也不是什么新鲜事了&#xff0c;Norton Antivirus从几年前的版本就开始用了&#xff0c;vs.net2002中的开始页也用了…

html css导航栏字体图标,HTML+CSS入门之两种图标字体库

本篇教程介绍了HTMLCSS入门之两种图标字体库&#xff0c;希望阅读本篇文章以后大家有所收获&#xff0c;帮助大家HTMLCSS入门。<## 0. 前言比较基础的图标加载&#xff1a;和块元素的背景background: url(./x.png).页面多图标时&#xff0c;使用雪碧图(多个png压缩成一个png…

垃圾收集算法,垃圾收集器_弱,弱,最弱,利用专家参考来管理垃圾收集器

垃圾收集算法,垃圾收集器何时以及何时不使用Java中的专家引用 弱引用&#xff0c;软引用和幻像引用既危险又强大。 如果以错误的方式使用它们&#xff0c;则会破坏JVM性能。 但是&#xff0c;如果使用正确的方法&#xff0c;它们可以大大提高性能和程序清晰度。 弱引用和软引用…

ESP8266—“ICACHE_FLASH_ATTR”宏

问&#xff1a;ESP8266_NONOS_SDK中ICACHE_FLASH_ATTR宏的用途是什么&#xff1f;我看到它取决于ICACHE_FLASH&#xff0c;但我不知道何时应该定义该符号。什么时候需要包括它&#xff1f;答&#xff1a;对于ESP8266_NONOS_SDK&#xff0c;用ICACHE_FLASH_ATTR编译的函数编译到…

layui网页html编辑器,layui使用富文本编辑器

HTML代码&#xff1a;这里的原理是你输入的内容会经过处理插入到文本区域textarea中js代码&#xff1a;/*** 文本编辑器*/layui.use([form, layedit], function(){var layedit layui.layedit;//上传图片,必须放在 创建一个编辑器前面layedit.set({uploadImage: {url: upload /…

Java应用程序性能监视:复杂的分布式应用程序的端到端性能

通过从应用程序中学习企业APM产品&#xff0c;发现更快&#xff0c;更高效的性能监控。 参加AppDynamics APM导览&#xff01; 在最复杂和分布式环境中端到端监视Java应用程序性能-专注于业务事务。 自动发现的业务交易&#xff0c;动态基准&#xff0c;代码级诊断和虚拟作战室…

C#设计模式(2)——简单工厂模式

一、引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工厂模式。 二、简单工厂模式的介绍 说到简单工厂&#xff0c;自然的第一个疑问当然就是什…

计算机应用基础课程基本要求,计算机应用基础课程标准

《计算机应用基础》课程标准一、课程性质&#xff1a;《计算机应用基础》课程是中职学校各专业学生必修的一门公共基础课程&#xff0c;具有很强的实践性和应用性&#xff0c;是各行各业从事现代化办公、计算机设计及应用等领域人材所必须具备的理论知识和实践技能。通过本课程…

S3C2410 bootloader ----VIVI阅读笔记 (转)下

1 static inline void mem_mapping_linear(void) 2 { 3 unsigned long pageoffset, sectionNumber; 4 putstr_hex("MMU table base address 0x", (unsigned long) mmu_tlb_base); 5 /* 4G 虚拟地址映射到相同的物理地址. not cacacheable, no…

华南理工网络计算机基础知识,2019年华南理工大学网络教育计算机基础随堂练习题第一章.docx...

计算机基础知识第一节 计算机的基本概念随堂练习提交截止时间&#xff1a;2019-06-15 23:59:59本次练习有题&#xff0c;你已做题&#xff0c;已提交题&#xff0c;其中答对题。当前页有6题&#xff0c;你已做6题&#xff0c;已提交6题&#xff0c;其中答对6题。1.(单选题)? 计…

orm jdbc_Spring Data JDBC通用DAO实现–迄今为止最轻量的ORM

orm jdbc我很高兴宣布Spring Data JDBC存储库项目的第一个版本。 这个开源库的目的是为基于Spring框架中 JdbcTemplate关系数据库提供通用&#xff0c;轻量且易于使用的DAO实现&#xff0c;与项目的Spring Data 框架兼容。 设计目标 轻巧&#xff0c;快速且开销低。 只有少数几…

NOIP模拟测试9「随·单·题」

liu_runda出的题&#xff0c;先$\%\%\%\%\%\%\%\%\%\%\%$为敬 随 考试时没有Qj 然后甚至没做,甚至没交 我不知道我怎么想的 这个题挺难改 你需要用到 循环矩阵快速幂,矩阵快速幂优化,打表找规律的基础 题解 首先我们可以列出来一个普通的dp式子 设f为第i次操作,操作后x变为j的概…

es5直接引入html文件,ES6+转ES5(webpack+babel、指定多个js文件、自动注入)

接续上篇ES6转ES5&#xff0c;本篇将使用webpack和babel将多个不同目录下指定的多个ES6语法的js文件编译为ES5&#xff0c;并将编译后的文件配置注入对应的html文件。一、新建项目&#xff0c;目录如下二、执行命令初始化项目cnpm init -y执行成功后会生成文件&#xff1a;pack…