zoukankan      html  css  js  c++  java
  • 【分治】动态点分治 ([ZJOI2007]捉迷藏)

    动态点分治

    先看一道题目 [ZJOI2007]捉迷藏

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

    一、点分树

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

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

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

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

    二、维护结点信息

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

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

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

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

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

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

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

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

    空间复杂度:O(N)

      1 #include<bits/stdc++.h>
      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<int>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]]<dep[top[y]]) swap (x,y);
     65         x=Fa[top[x]];
     66     }
     67     return dep[x]<dep[y]?x:y;
     68 }
     69 void getrt (int u,int fa)
     70 {
     71     size[u]=1,maxp[u]=0;
     72     if (!col[u]) s[++tot]=u;
     73     for (int i=head[u];i!=0;i=e[i].nxt)
     74         if (e[i].v!=fa&&!used[e[i].v])
     75         {
     76             getrt (e[i].v,u);
     77             size[u]+=size[e[i].v];
     78             maxp[u]=max (maxp[u],size[e[i].v]);
     79         }
     80     maxp[u]=max (maxp[u],sum-size[u]);
     81     if (maxp[u]<maxp[root]) root=u;
     82 }
     83 int f[MAXN];
     84 int getdis (int x,int y)
     85 {
     86     return dist[x]+dist[y]-(dist[lca (x,y)]<<1);
     87 }
     88 int divide (int u)
     89 {
     90     used[u]=1;if (!col[u]) b[u].push (0);
     91     for (int i=1;i<=tot;i++) a[u].push (getdis (f[u],s[i]));
     92     for (int i=head[u];i!=0;i=e[i].nxt)
     93         if (!used[e[i].v])
     94         {
     95             maxp[root=tot=0]=sum=size[e[i].v],getrt (e[i].v,0);
     96             f[root]=u;
     97             int child=divide (root);
     98             b[u].push (a[child].top ());
     99         }
    100     ans.push (b[u].len ());
    101     return u;
    102 }
    103 void modify (int x,int c)
    104 {
    105     int l1=b[x].len (),l2,s1,s2;b[x].op (0,c);
    106     if (l1!=(l2=b[x].len ())) ans.pop (l1),ans.push (l2);
    107     for (int u=x,fa=f[u];fa;fa=f[u=fa])
    108     {
    109         s1=a[u].top (),a[u].op (getdis (fa,x),c),s2=a[u].top();
    110         if (s1!=s2)
    111         {
    112             l1=b[fa].len ();
    113             if (s1!=-INF) b[fa].pop (s1);
    114             if (s2!=-INF) b[fa].push (s2);
    115             l2=b[fa].len ();
    116             if (l1!=l2) ans.pop (l1),ans.push (l2);
    117         }
    118     }
    119 }
    120 int main()
    121 {
    122     n=read ();
    123     for (int i=1;i<n;i++)
    124     {
    125         int u=read (),v=read ();
    126         add (u,v,1);add (v,u,1);
    127     }
    128     dfs1 (1,0);dfs2 (1,1);
    129     maxp[root]=sum=n,getrt (1,0);
    130     divide (root);
    131     q=read ();
    132     while (q--)
    133     {
    134         scanf ("%s",opt+1);
    135         if (opt[1]=='C')
    136         {
    137             int x=read ();col[x]^=1;
    138             modify (x,col[x]);
    139         }
    140         else printf ("%d
    ",ans.top ()); 
    141     }
    142     return 0;
    143 }
  • 相关阅读:
    js炫酷效果
    程序员的执着
    [心得]docker学习笔记
    [心得笔记]多线程之间的内存可见性问题
    Docker入门
    [心得体会]jvm
    redis学习总结
    [心得]redis集群环境搭建的错误
    Linux安装mysql5.7版本
    Cent OS下安装JDK11
  • 原文地址:https://www.cnblogs.com/PaulShi/p/10057768.html
Copyright © 2011-2022 走看看