码迷,mamicode.com
首页 > 其他好文 > 详细

动态点分治及其应用

时间:2018-09-10 22:22:59      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:getc   algo   直接   sum   std   can   操作   push   www.   

一般如果需要大规模处理树上路径,点分治是一个不错的选择

在解决树上路径满足某种属性的数量统计方面有着很大的作用

点分治的核心抄dalao的两句话:

1.对于端点是自己子树上的任意一条路径,它要么经过自己,要么在自己的某个子树中 
2.获取树的重心来把树的深度从O(n)变到O(logn)

然后稍微说一说动态点分治,在原来点分治的基础上,添加一个fa数组

我们相当于通过fa数组重建了一棵点分树。这棵点分树的深度是最多logn的

在点分治中,每个点都会作为重心,但它们作为重心的时候管辖的范围不同

对于某个点,我们维护的是这个点作为重心时所管辖的那一坨树的信息

树上的动态点分治就相当于序列上的线段树??

可以理解为序列的区间问题用线段树维护,树的区间问题用点分树来维护?

所以我们要修改一个点的点权的时候,我们就直接在点分树暴跳父亲,然后因为点分树的性质从而保证复杂度是O(nlogn)

这里很像线段树的点修改

那么点分治的过程就相当于建树的过程喽?

据说可以用线段树维护括号序列来解决这个问题?周末之前看来学不完了,先挖个坑

然后说一下BZOJ1095的题面

给定一棵树,每个节点要么是黑色,要么是白色,能执行两个操作:
把某一个点取反色,返回距离最远的黑色点对

把每次分治的重心连成一棵树,树的深度是logn,每次修改一个结点只影响它到树根的一条链

黄学长说实现起来要用三层堆?

C.每个重心存所有子树到其距离
B.每个重心存各个子树最大值,即子结点堆C的最大值
A.全局一个堆,维护答案最大值,存每个堆B的最大值和次大值之和

为了赶进度,最近的更博只能抄代码了,实在惭愧。

  1 #include<set>
  2 #include<map>
  3 #include<ctime>
  4 #include<queue>
  5 #include<cmath>
  6 #include<cstdio>
  7 #include<vector>
  8 #include<cstring>
  9 #include<cstdlib>
 10 #include<iostream>
 11 #include<algorithm>
 12 #define inf 1000000000
 13 #define mod 1000000007
 14 #define pa pair<int,int>
 15 #define ll long long 
 16 using namespace std;
 17 inline int read()
 18 {
 19     int x=0,f=1;char ch=getchar();
 20     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
 21     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 22     return x*f;
 23 }
 24 int bin[20],Log[200005];
 25 int n,m,G,cnt,dfn,sum,tot;
 26 int size[100005],f[100005],deep[100005],last[100005];
 27 int mn[18][200005],pos[100005],fa[100005];
 28 bool vis[100005],clo[100005];
 29 struct edge{
 30     int to,next;
 31 }e[200005];
 32 void insert(int u,int v)
 33 {
 34     e[++cnt]=(edge){v,last[u]};last[u]=cnt;
 35     e[++cnt]=(edge){u,last[v]};last[v]=cnt;
 36 }
 37 struct heap{
 38     priority_queue<int> A,B;
 39     void push(int x){
 40         A.push(x);
 41     }
 42     void erase(int x){
 43         B.push(x);
 44     }
 45     void pop(){
 46         while(B.size()&&A.top()==B.top())
 47             A.pop(),B.pop();
 48         A.pop();
 49     }
 50     int top(){
 51         while(B.size()&&A.top()==B.top())
 52             A.pop(),B.pop();
 53         if(!A.size())return 0;
 54         return A.top();
 55     }
 56     int size(){
 57         return A.size()-B.size();
 58     }
 59     int stop(){
 60         if(size()<2)return 0;
 61         int x=top();pop();
 62         int y=top();push(x);
 63         return y;
 64     }
 65 }A,B[100005],C[100005];
 66 void dfs(int x,int fa)
 67 {
 68     mn[0][++dfn]=deep[x];
 69     pos[x]=dfn;
 70     for(int i=last[x];i;i=e[i].next)
 71         if(e[i].to!=fa)
 72         {
 73             deep[e[i].to]=deep[x]+1;
 74             dfs(e[i].to,x);
 75             mn[0][++dfn]=deep[x];
 76         }
 77 }
 78 void getrt(int x,int fa)
 79 {
 80     size[x]=1;f[x]=0;
 81     for(int i=last[x];i;i=e[i].next)
 82         if(e[i].to!=fa&&!vis[e[i].to])
 83         {
 84             getrt(e[i].to,x);
 85             size[x]+=size[e[i].to];
 86             f[x]=max(f[x],size[e[i].to]);
 87         }
 88     f[x]=max(f[x],sum-size[x]);
 89     if(f[x]<f[G])G=x;
 90 }
 91 void divi(int x,int f)
 92 {
 93     fa[x]=f;vis[x]=1;
 94     for(int i=last[x];i;i=e[i].next)
 95         if(!vis[e[i].to])
 96         {
 97             sum=size[e[i].to];G=0;
 98             getrt(e[i].to,x);
 99             divi(G,x);
100         }
101 }
102 int rmq(int x,int y)
103 {
104     x=pos[x];y=pos[y];
105     if(y<x)swap(x,y);
106     int t=Log[y-x+1];
107     return min(mn[t][x],mn[t][y-bin[t]+1]);
108 }
109 int dis(int x,int y)
110 {
111     return deep[x]+deep[y]-2*rmq(x,y);
112 }
113 void turn_off(int u,int v)
114 {
115     if(u==v)
116     {
117         B[u].push(0);
118         if(B[u].size()==2)A.push(B[u].top());
119     }
120     if(!fa[u])return;
121     int f=fa[u],D=dis(f,v),tmp=C[u].top();
122     C[u].push(D);
123     if(D>tmp)
124     {
125         int mx=B[f].top()+B[f].stop(),size=B[f].size();
126         if(tmp)B[f].erase(tmp);
127         B[f].push(D);
128         int now=B[f].top()+B[f].stop();
129         if(now>mx)
130         {
131             if(size>=2)A.erase(mx);
132             if(B[f].size()>=2)A.push(now);
133         }
134     }
135     turn_off(f,v);
136 }
137 void turn_on(int u,int v)
138 {
139     if(u==v)
140     {
141         if(B[u].size()==2)A.erase(B[u].top());
142         B[u].erase(0);
143     }
144     if(!fa[u])return;
145     int f=fa[u],D=dis(f,v),tmp=C[u].top();
146     C[u].erase(D);
147     if(D==tmp)
148     {
149         int mx=B[f].top()+B[f].stop(),size=B[f].size();
150         B[f].erase(D);
151         if(C[u].top())B[f].push(C[u].top());
152         int now=B[f].top()+B[f].stop();
153         if(now<mx)
154         {
155             if(size>=2)A.erase(mx);
156             if(B[f].size()>=2)A.push(now);
157         }
158     }
159     turn_on(f,v);
160 }
161 int main()
162 {
163     bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
164     Log[0]=-1;for(int i=1;i<=200000;i++)Log[i]=Log[i>>1]+1;
165     n=read();
166     for(int i=1;i<n;i++)
167     {
168         int u=read(),v=read();
169         insert(u,v);
170     }
171     dfs(1,0);
172     for(int i=1;i<=Log[dfn];i++)
173         for(int j=1;j<=dfn;j++)
174             if(j+bin[i]-1<=dfn)
175                 mn[i][j]=min(mn[i-1][j],mn[i-1][j+bin[i-1]]);
176     G=0;f[0]=inf;sum=n;
177     getrt(1,0);divi(G,0);
178     for(int i=1;i<=n;i++)C[i].push(0);
179     for(int i=1;i<=n;i++)clo[i]=1;
180     for(int i=1;i<=n;i++)
181     {
182         turn_off(i,i);
183         tot++;
184     }
185     char ch[2];
186     m=read();
187     while(m--)
188     {
189         scanf("%s",ch+1);
190         if(ch[1]==G)
191         {
192             if(tot<=1)printf("%d\n",tot-1);
193             else printf("%d\n",A.top());
194         }
195         else 
196         {
197             int x=read();
198             if(clo[x])turn_on(x,x),tot--;
199             else turn_off(x,x),tot++;
200             clo[x]^=1;
201         }
202     }
203     return 0;
204 }

 

动态点分治及其应用

标签:getc   algo   直接   sum   std   can   操作   push   www.   

原文地址:https://www.cnblogs.com/aininot260/p/9623445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!