• 关于树上的简单操作(暂时)


    • 倍增求LCA
     1 #include<cstdio>
     2 #include<iostream>
     3 #define re register
     4 #define in inline
     5 #define N 500010
     6 #define M 500010
     7 using namespace std;
     8 in int read(){
     9     int x=0,f=1; char c=getchar();
    10     while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*f;
    13 }
    14 struct node{
    15     int next,to;
    16 }edge[M<<1];
    17 int n,q,s,cnt;
    18 int head[M<<1],f[25][N],dep[N]; 
    19 
    20 in void add(int x,int y){
    21     edge[++cnt].next=head[x];
    22     edge[cnt].to=y;
    23     head[x]=cnt; 
    24 }
    25 
    26 void dfs(int u,int deep){
    27     dep[u]=deep;
    28     for(re int i=head[u];i;i=edge[i].next){
    29         int v=edge[i].to;
    30         if(!dep[v]) dfs(v,deep+1);
    31         f[0][v]=u;    //特别注意:需在dfs后更新,不然会被更新回去 
    32     }                //无向图中要保持向根性,所以if(!dep[v])也必不可少 
    33 }
    34 
    35 in int lca(int x,int y){
    36     if(dep[x]<dep[y]) swap(x,y);
    37     for(int i=20;i>=0;i--){    //跳至同一深度 
    38         if(dep[f[i][x]]>=dep[y])
    39         x=f[i][x];
    40         if(x==y) return x;    //跳至同一点(x),x即是lca 
    41     }
    42     
    43     for(int i=20;i>=0;i--){
    44         if(f[i][x]!=f[i][y])    //不是同一点,往上跳 
    45             x=f[i][x],y=f[i][y];
    46     }
    47     return f[0][x];    //同深度不同点的父节点,即lca 
    48 }
    49 
    50 int main()
    51 {
    52     n=read(),q=read(),s=read();
    53     for(re int i=1;i<n;i++){
    54         int u=read(),v=read();
    55         add(u,v),add(v,u);
    56     }
    57     f[0][s]=s;
    58     dfs(s,1);
    59     for(re int i=1;(1<<i)<=n;i++) //'x<<y' 表示 "x左移2^y" 
    60         for(re int j=1;j<=n;j++)
    61             f[i][j]=f[i-1][f[i-1][j]];
    62     for(re int i=1;i<=q;i++){
    63         int x=read(),y=read();
    64         printf("%d
    ",lca(x,y));
    65     }
    66     return 0;
    67 }
    • 树上差分
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define re register
     5 #define in inline
     6 #define N 50010
     7 using namespace std;
     8 int read(){
     9     int x=0,f=1; char c=getchar();
    10     while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*f;
    13     
    14 }
    15 struct node{
    16     int next,to;
    17 }edge[N<<1];
    18 int n,m,ans,sum,cnt;
    19 int head[N<<1],p[N],dep[N],f[N][25];
    20 
    21 in void add(int x,int y){
    22     edge[++cnt].next=head[x];
    23     edge[cnt].to=y;
    24     head[x]=cnt;
    25 }
    26 in void solve(int u,int fa){
    27     dep[u]=dep[fa]+1,f[u][0]=fa;
    28     for(int i=0;f[u][i];i++) f[u][i+1]=f[f[u][i]][i];
    29     for(int i=head[u];i;i=edge[i].next){
    30         int v=edge[i].to;
    31         if(v!=fa) solve(v,u);
    32     }
    33 }
    34 in int LCA(int u,int v){
    35     if(dep[u]>dep[v]) swap(u,v);
    36     for(re int i=20;i>=0;i--) if(dep[u]<=dep[v]-(1<<i)) v=f[v][i];
    37     if(u==v) return u;
    38     for(re int i=20;i>=0;i--) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    39     return f[u][0];
    40 }
    41 in void get(int u,int fa){
    42     for(int i=head[u];i;i=edge[i].next){
    43         int v=edge[i].to;
    44         if(v!=fa){
    45             get(v,u);
    46             p[u]+=p[v];
    47         }
    48     }
    49     ans=max(ans,p[u]);
    50 }
    51 int main()
    52 {
    53     n=read(),m=read();
    54     for(re int i=1;i<n;i++){
    55         int u=read(),v=read();
    56         add(u,v),add(v,u);
    57     }
    58     solve(1,0);
    59     for(re int i=1;i<=m;i++){
    60         int u=read(),v=read();
    61         int lca=LCA(u,v);
    62         p[u]++,p[v]++,p[lca]--,p[f[lca][0]]--;
    63     }
    64     get(1,0);
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
  • 相关阅读:
    伯努利数学习笔记
    贝尔数学习笔记
    LuoguP5075 [JSOI2012]分零食
    LuoguP5748 集合划分计数
    LuoguP3338 [ZJOI2014]力
    LuoguP5488 差分与前缀和
    BZOJ4833 [Lydsy1704月赛]最小公倍佩尔数
    FFT&NTT学习笔记
    csp2019游记
    与图论的邂逅09:树上启发式合并
  • 原文地址:https://www.cnblogs.com/RR-Jin/p/11835377.html
Copyright © 2020-2023  润新知