• 图论:动态点分治


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

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

    点分治的核心抄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 }
  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/aininot260/p/9623445.html
Copyright © 2020-2023  润新知