• 图论:动态点分治


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

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

    点分治的核心抄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
    ",tot-1);
    193             else printf("%d
    ",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 }
  • 相关阅读:
    干将莫邪
    Rancher
    Rancher 1.6 版本 只能在 linux 下用
    野蛮人大作战
    Oracle
    Gradle
    正则表达式 我遇到的
    Redis
    NestJS 用TypeScript开发 nodeJS后端
    Koa2
  • 原文地址:https://www.cnblogs.com/aininot260/p/9623445.html
Copyright © 2020-2023  润新知