1. 程式人生 > 實用技巧 >CentOS 7 靜態IP配置

CentOS 7 靜態IP配置

1.簡介

這其實是一個很神奇的東西,分為三種,其中比較常見的是:重鏈剖分,長鏈剖分;

那麼·這個用來解決什麼問題呢? 這個資料結構支援對於樹上的·兩個節點x,y,將其兩點間的路徑上的所有數加上一個值看,並且可以查詢x到y的最短路上邊的權值和。

3.相關概念

樹鏈剖分:一種對樹進行劃分的演算法,它先通過輕重邊剖分將樹分為多條鏈,保證每個點屬於且只屬於一條鏈,然後再通過資料結構(樹狀陣列、BST、SPLAY、線段樹等)來維護每一條鏈。
重兒子:一個結點的所有子樹中,樹的大小(即包括根結點的結點的個數)最大的子樹之一的根結點(也就是當前結點的一個子節點),稱為該節點的重兒子,注意,重兒子只能有1個,當出現

多個子樹大小相同且都為最大時,我們隨機選取其中一個作為重兒子,其他的則看做輕兒子。

輕兒子:一個結點的所有子結點中不是重兒子的結點
重鏈:一個結點與他的重兒子之間連的邊

*注意,由於重兒子的定義,一棵樹的重鏈剖分方式可能不唯一

3.樹鏈剖分細節

為了對一棵樹進行重鏈剖分,我們維護以下幾個陣列:

fa[x]:結點x的父親 son[x]:結點x的重兒子 sz[x]:結點x的子樹大小 dep[x]:結點x的深度 top[x]:結點x所在重鏈的頂點 seg[x]:結點x線上段樹中的編號 rev[x]:線段樹中結點x在原陣列中的編號

用兩個DFS對其進行維護

第一個dfs處理的是前4個數組 第二個dfs處理的是後3個數組

4.推薦例題

洛谷:P4315 月下“毛景樹”

5.下面上程式碼:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<vector>
  7 #define N 100005
  8 
  9 using namespace std;
 10 
 11 vector<int > adj[N];
 12 int n,m,r,p,cnt=0;
13 int son[N],deep[N],fa[N],size[N]; 14 int id[N],top[N],w[N]; 15 long long c1[N],c2[N]; 16 17 int lowbit(int x) 18 { 19 return x&(-x); 20 } 21 22 void add(int l,int r,int x) 23 { 24 x%=p; 25 int ad1=(long long)(l-1)*x%p; 26 int ad2=(long long)r*x%p; 27 for(int t=l;t<=n;t+=lowbit(t)) 28 { 29 c1[t]=(c1[t]+x)%p; 30 c2[t]=(c2[t]+ad1)%p; 31 } 32 for(int t=r+1;t<=n;t+=lowbit(t)) 33 { 34 c1[t]=(c1[t]-x)%p; 35 c1[t]=(c1[t]+p)%p; 36 c2[t]=(c2[t]-ad2)%p; 37 c2[t]=(c2[t]+p)%p; 38 } 39 40 } 41 42 int qwq(int i) 43 { 44 int res=0; 45 for(int t=i;t>0;t-=lowbit(t)) 46 { 47 res=(res+(long long )i*c1[t]%p)%p; 48 res=(res-c2[t])%p; 49 res=(res+p)%p; 50 } 51 return res; 52 } 53 54 int query(int l,int r) 55 { 56 int res=(qwq(r)-qwq(l-1))%p; 57 return (res+p)%p; 58 } 59 //======================================================================= 60 61 int Read() 62 { 63 int num=0,k=1; 64 char c=getchar(); 65 while(c!='-'&&(c<'0'||c>'9')) c=getchar(); 66 if(c=='-') 67 { 68 k=-1; 69 c=getchar(); 70 } 71 while(c>='0'&&c<='9') 72 { 73 num=(num<<1)+(num<<3)+c-'0'; 74 c=getchar(); 75 } 76 return num*k; 77 } 78 79 void print(int x) 80 { 81 if(x>9) print(x/10); 82 putchar(x%10+'0'); 83 } 84 85 void dfs1(int u,int f) 86 { 87 fa[u]=f; 88 size[u]=1; 89 deep[u]= deep[f]+1; 90 int v,t=-1,l=adj[u].size(); 91 for(int i=0;i<l;++i) 92 { 93 v=adj[u][i]; 94 if(v==f) continue; 95 dfs1(v,u); 96 size[u]+=size[v]; 97 if(size[v]>t) 98 { 99 t=size[v]; 100 son[u]=v; 101 } 102 } 103 } 104 105 void dfs2(int u,int f) 106 { 107 top[u]=f; 108 id[u]=++cnt; 109 if(w[u]!=0) add(id[u],id[u],w[u]); 110 if(son[u]==0) return ; 111 dfs2(son[u],f); 112 int v,l=adj[u].size(); 113 for(int i=0;i<l;++i) 114 { 115 v=adj[u][i]; 116 if(v==son[u]||v==fa[u]) continue; 117 dfs2(v,v); 118 } 119 } 120 121 int queryPath(int u,int v) 122 { 123 int res=0; 124 while(top[u]!=top[v]) 125 { 126 if(deep[top[u]]<deep[top[v]]) swap(u,v); 127 res=(res+query(id[top[u]],id[u]))%p; 128 u=fa[top[u]]; 129 } 130 if(deep[u]>deep[v]) swap(u,v); 131 res=(res+query(id[u],id[v]))%p; 132 return res; 133 } 134 135 void addPath(int u,int v,int k) //路徑上所有的點的權值加上k 136 { 137 k%=p; 138 while(top[u]!=top[v])//倍增求lca 139 { 140 if(deep[top[u]]<deep[top[v]]) swap(u,v);//保證u的鏈頭的深度大於v的鏈頭 141 add(id[top[u]],id[u],k);//當前這一條鏈加k 142 u=fa[top[u]];//進入下一條鏈 143 } 144 if(deep[u]>deep[v]) swap(u,v); 145 add(id[u],id[v],k); 146 } 147 148 int querySon(int u) 149 { 150 return query(id[u],id[u]+size[u]-1); 151 } 152 153 void addSon(int u,int k) 154 { 155 k%=p; 156 add(id[u],id[u]+size[u]-1,k); 157 } 158 159 int main () 160 { 161 int u,v; 162 n=Read(); 163 m=Read(); 164 r=Read(); 165 p=Read(); 166 for(int i=1;i<=n;++i) w[i]=Read(); 167 for(int i=1;i<n;++i) 168 { 169 u=Read(); 170 v=Read(); 171 adj[u].push_back(v); 172 adj[v].push_back(u); 173 } 174 dfs1(r,0); 175 dfs2(r,r); 176 int ans,op,x,y,z; 177 while(m--) 178 { 179 op=Read(); 180 x=Read(); 181 if(op==1) 182 { 183 y=Read(); 184 z=Read(); 185 addPath(x,y,z); 186 continue; 187 } 188 if(op==2) 189 { 190 y=Read(); 191 ans=queryPath(x,y); 192 printf("%d\n",ans); 193 continue; 194 } 195 if(op==3) 196 { 197 z=Read(); 198 addSon(x,z); 199 continue; 200 } 201 ans = querySon(x); 202 printf("%d\n",ans); 203 } 204 return 0; 205 }