博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【分治】动态点分治 ([ZJOI2007]捉迷藏)
阅读量:4677 次
发布时间:2019-06-09

本文共 2435 字,大约阅读时间需要 8 分钟。

动态点分治

先看一道题目 

显然如果不带修改O(N)的树形动规和O(NlogN)的静态点分治都可以切掉这道题

一、点分树

考虑点分治,对于每一个分治区域树的重心的答案只会与其所有子区域树有关,所以我们可以再构建一颗点分树:

在点分治的过程中,我们把每个区域树的重心和其子区域树的重心建立父子关系,形成了一颗新的树,称为点分树。

点分树的性质:1、一颗点分树的深度为严格logN的

                         2、当修改一个结点事,只会对其父亲结点造成影响z

二、维护结点信息

对于这道题,我们只需维护每个结点上的最大链和次大链,我们可以对于每个结点建两个大根堆:

A:关键字:原分治区域树中以该结点为链的一段的所有链的长度

B:关键字:原分治树中以该结点为根时,每个子树中最长链的长度

所以我们可以得出每个分支区域树中,B中的第一大元素和第二大元素的和即是答案

B由该结点为根的子树中每个A的最大值组成

最后我们只需用树链剖分求lca,并用差分求树上任意两点距离即可

三、时间复杂度&空间复杂度

时间复杂度为点分治的NlogN+堆的logN == O(Nlog2N)

空间复杂度:O(N)

1 #include
2 #define INF 0x3f3f3f3f 3 #define MAXN 100010 4 using namespace std; 5 inline int read () 6 { 7 int w=1,s=0; 8 char ch=getchar (); 9 while (ch<'0'||ch>'9'){
if (ch=='-') w=-1;ch=getchar ();} 10 while ('0'<=ch&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar (); 11 return s*w; 12 } 13 struct Heap{ 14 priority_queue
A,B;int size; 15 Heap(){size=0;} 16 void push (int x){A.push (x),size++;} 17 void pop (int x){B.push (x),size--;} 18 int top (){
while (!B.empty ()&&A.top ()==B.top ()) A.pop (),B.pop ();return size?A.top ():-INF;} 19 int len () 20 { 21 if (size==0) return -1; 22 if (size==1) return 0; 23 int x=top ();pop (x);int y=top ();push (x); 24 return x+y; 25 } 26 void op (int x,int c){c?pop (x):push (x);} 27 }a[MAXN],b[MAXN],ans; 28 struct edge{ 29 int v,w,nxt; 30 }e[MAXN<<1]; 31 int n,q,cnt,root,sum,tot; 32 int head[MAXN],size[MAXN],maxp[MAXN],s[MAXN],col[MAXN]; 33 int Fa[MAXN],dep[MAXN],son[MAXN],dist[MAXN],top[MAXN]; 34 bool used[MAXN]; 35 char opt[MAXN]; 36 void add (int u,int v,int w) 37 { 38 e[++cnt].v=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt; 39 } 40 void dfs1 (int u,int fa) 41 { 42 Fa[u]=fa,size[u]=1,dep[u]=dep[fa]+1; 43 for (int i=head[u];i!=0;i=e[i].nxt) 44 if (e[i].v!=fa) 45 { 46 dist[e[i].v]=dist[u]+e[i].w; 47 dfs1 (e[i].v,u); 48 size[u]+=size[e[i].v]; 49 if (size[e[i].v]>size[son[u]]) son[u]=e[i].v; 50 } 51 } 52 void dfs2 (int u,int topf) 53 { 54 top[u]=topf; 55 if (son[u]) dfs2 (son[u],topf); 56 for (int i=head[u];i!=0;i=e[i].nxt) 57 if (e[i].v!=Fa[u]&&e[i].v!=son[u]) 58 dfs2 (e[i].v,e[i].v); 59 } 60 int lca (int x,int y) 61 { 62 while (top[x]]!=top[y]) 63 { 64 if (dep[top[x]]

 

转载于:https://www.cnblogs.com/PaulShi/p/10057768.html

你可能感兴趣的文章
商业选址5A法则
查看>>
POJ 1191 棋盘分割(区间DP)题解
查看>>
文件同步服务器,iis 集群 ,代码同步(一)
查看>>
JS之模板技术(aui / artTemplate)
查看>>
【Tomcat】Tomcat Connector的三种运行模式【bio、nio、apr】
查看>>
Mysql-2-数据库基础
查看>>
python把源代码打包成.exe文件
查看>>
PhotoshopCS5中将单位修改成百分比
查看>>
Ubuntu 中sendmail 的安装、配置与发送邮件的具体实现
查看>>
时隔2月,我的第二篇
查看>>
[导入]C++ OpenGL底层和C# GUI无缝联合!
查看>>
调试程序Bug-陈棚
查看>>
STM32 寄存器库和固件库
查看>>
第11周表格
查看>>
linux运维云计算课程学习,Linux云计算面试时遇到的问题
查看>>
Abiword对话框资源
查看>>
跟我一起写 Makefile
查看>>
C# uri
查看>>
GPS定位 测试
查看>>
前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查
查看>>