区队A 最近公共祖先
模板
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m,s;
cin>>n>>m>>s;
for(int i = 1;i<n;i++)
{
int x,y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
dep[s] = 0;
size = 0;
dfs(s);
init();
for(int i= 1;i<=m;i++){
int x,y;
cin>>x>>y;
cout<<lca(x,y)<<'\n';
}
return 0;
}
P8855 [POI 2002 R1] 商务旅行
首先可以设a = lca(x,y)
则x到y的距离为\(dep[x]+dep[y] - 2*dep[a]\)
Code:
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
for(int i = 1;i<n;i++){
int a,b;
cin>>a>>b;
e[a].push_back(b);
e[b].push_back(a);
}
int m,cur;
cin>>m>>cur;
dep[1] = 0;
size = 0;
dfs(1);
init();
int ans = 0;
for(int i = 2;i<=m;i++)
{
int nxt,a;
cin>>nxt;
a = lca(cur,nxt);
ans += dep[cur] + dep[nxt] - 2 * dep[a];
cur = nxt;
}
cout<<ans;
return 0;
}
P2420 让我们异或吧
公式:\(dis[x] xor dis[y] ^ dis[a] ^ dis[a]\) 化简 -> \(dis[x] xor dis[y]\)
Code:
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
int size;
int sum[100010];
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<pii> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i].first,m = e[x][i].second;
if(y != fa[x])
{
fa[y] = x;
sum[y] = sum[x] ^ m;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
for(int i = 1;i<n;i++){
int a,b,w;
cin>>a>>b>>w;
e[a].push_back({b,w});
e[b].push_back({a,w});
}
int m,cur;
cin>>m;
sum[1] = 0;
size = 0;
dfs(1);
init();
int ans = 0;
for(int i = 1;i<=m;i++)
{
int u ,v;
cin>>u>>v;
cout<<(sum[u] ^ sum[v]) << '\n';
}
return 0;
}
P10113 [GESP202312 八级] 大量的工作沟通
结论:\(lca({x,y,z}) = lca(lca(x,y),z)\)
Code:
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
int maxx[500010];
vector<int> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
maxx[y] = max(y,maxx[x]);
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m,s;
cin>>n;
for(int i = 1;i<n;i++)
{
cin>>fa[i];
e[fa[i]].push_back(i);
}
dep[0] = 0;
size = 0;
dfs(0);
init();
int q;
cin>>q;
for(int i= 1;i<=q;i++){
int m,cur;
cin>>m>>cur;
for(int j = 2;j<=m;j++){
int x;
cin>>x;
cur = lca(cur,x);
}
cout<<maxx[cur]<<'\n';
}
return 0;
}
P3128 [USACO15DEC] Max Flow P
树上差分
Code:
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
int diff[500010];
int maxx;
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
int calc(int x){
int sum = diff[x];
for(int i = 0;i<e[x].size();i ++){
int y = e[x][i];
if(y != fa[x]){
int tmp = calc(y);
// maxx = max(maxx,tmp);
sum += tmp;
}
}maxx = max(maxx,sum);
return sum;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,k;
cin>>n>>k;
for(int i = 1;i<n;i++)
{
int x,y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
dep[1] = 0;
size = 0;
dfs(1);
init();
for(int i= 1;i<=k;i++){
int u,v;
cin>>u>>v;
int a=lca(u,v);
++diff[u];
++diff[v];
--diff[a];
if(dep[a] > 0) -- diff[fa[a]];
}
maxx = 0;
calc(1);
cout<<maxx;
return 0;
}
P4281 [AHOI2008] 紧急集合 / 聚会
\(a = lca(x,y)\) ,\(b = lca(x,z)\),\(c = lca(y,z)\)
\(d[x] - d[a] + d[y] - d[b] + d[z] - d[b]\)
Code:
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m;
cin>>n>>m;
for(int i = 1;i<n;i++){
int a,b;
cin>>a>>b;
e[a].push_back(b);
e[b].push_back(a);
}
dep[1] = 0;
size = 0;
dfs(1);
init();
for(int i =1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
int xy = lca(x,y);
int xz = lca(x,z);
int yz = lca(y,z);
int pos;
if(xy == xz && xy == yz) pos = xy;
else if(xy == yz) pos = xz;
else if(xy == xz) pos = yz;
else pos = xy;
int ans = dep[x] + dep[y] + dep[z] - dep[xy] - dep[xz] - dep[yz];
cout<<pos<<' '<<ans<<'\n';
}
return 0;
}
P3398 仓鼠找 sugar
\(x = lca(a,b)\) \(y = lca(c,d)\) \(dep[x] >= dep[y]\)
y是x祖先
Code:
#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
euler[++size]= x;
pos[x] = size;
for(int i = 0 ;i < e[x].size() ; ++i)
{
int y = e[x][i];
if(y != fa[x])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
euler[++size] = x;
}
}
}
int min_dep(int lhs,int rhs)
{
return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
log_2[1] = 0;
for(int i = 2;i<=size;i++)
{
log_2[i] = log_2[i / 2] + 1;
}
for(int i = 1;i<=size;i++)
{
st[0][i] = euler[i];
}
for(int i = 1;i<=log_2[size];i++)
{
for(int j = 1;j + (1 << i) - 1 <= size;++j)
{
st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i - 1))]);
}
}
}
int query(int l,int r){
int tmp = log_2[r- l+ 1];
return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
int pos_x = pos[x],pos_y = pos[y];
if(pos_x > pos_y)
{
swap(pos_x, pos_y);
}
return query(pos_x,pos_y);
}
int calc(int x,int y){
int z= lca(x,y);
return dep[x] + dep[y] - 2 * dep[z];
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,q;
cin>>n>>q;
for(int i = 1;i<n;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dep[1] = 0;
size = 0;
dfs(1);
init();
for(int i = 1;i<=q;i++){
int a,b,c,d;
cin>>a>>b>>c>>d;
int x = lca(a,b),y = lca(c,d);
if(dep[x] < dep[y]){
swap(x,y);
swap(a,c);
swap(b,d);
}
cout<<(calc(c,x) + calc(x,d) == calc(c,d) ? "Y" : "N")<<'\n';
}
return 0;
}
P8972 『GROI-R1』 一切都已过去
转换成树上路径
2和5的因子数量
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 5;
const int inf = 1e16;
struct node {
int y, w, dlp;
};
int n, m, s = 1, dep[N], dp[N][21], dis[N], cnt2[N], cnt5[N], a[N];
vector<node> nbr[N];
int count_two(int x) {
if (x == 0) return inf;
int cnt = 0;
while (x % 2 == 0) {
cnt++;
x /= 2;
}
return cnt;
}
int count_five(int x) {
if (x == 0) return inf;
int cnt = 0;
while (x % 5 == 0) {
cnt++;
x /= 5;
}
return cnt;
}
void pre_lca(int cur, int fa) {
dp[cur][0] = fa;
dep[cur] = dep[fa] + 1;
for (int i = 1; (1 << i) <= dep[cur]; i++) {
dp[cur][i] = dp[dp[cur][i-1]][i-1];
}
for (auto i : nbr[cur]) {
int nxt = i.y;
if (nxt != fa) {
dis[nxt] = dis[cur] + i.dlp;
cnt2[nxt] = cnt2[cur] + count_two(i.w);
cnt5[nxt] = cnt5[cur] + count_five(i.w);
pre_lca(nxt, cur);
}
}
}
int lca(int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
for (int i = 20; i >= 0; i--) {
if (dep[x] <= dep[dp[y][i]]) {
y = dp[y][i];
}
}
if (x == y) return x;
for (int i = 20; i >= 0; i--) {
if (dp[x][i] != dp[y][i]) {
x = dp[x][i];
y = dp[y][i];
}
}
return dp[x][0];
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i < n; i++) {
int x, y;
double v;
cin >> x >> y >> v;
int dlp = 0;
while (v != floor(v)) {
v *= 10.0;
dlp++;
}
nbr[x].push_back((node){y, (int)floor(v), dlp});
nbr[y].push_back((node){x, (int)floor(v), dlp});
}
pre_lca(1, 0);
for (; m; m--) {
int x, y;
cin >> x >> y;
int tmp = lca(x, y);
if (min(cnt2[x] + cnt2[y] - 2 * cnt2[tmp] + count_two(a[x]),
cnt5[x] + cnt5[y] - 2 * cnt5[tmp] + count_five(a[x])) >=
dis[x] + dis[y] - 2 * dis[tmp]) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
return 0;
}
P6374 「StOI-1」树上询问
倍增法
Code:
#include<bits/stdc++.h>
using namespace std;
int fa[20][500010],dep[500010];
vector<int> e[500010];
int sz[500010];
int n,m,s;
void dfs(int x)
{
sz[x] = 1;
for(int y : e[x])
{
if(y == fa[0][x]) continue;
fa[0][y] = x;
dep[y] = dep[x] + 1;
for(int j = 0,a = x;fa[j][a] ; a = fa[j ++][a])
{
fa[j + 1][y]= fa[j][a];
}dfs(y);
sz[x] += sz[y];
}
}
int lca(int x,int y){
if(dep[x] < dep[y]) swap(x,y);
int diff = dep[x] - dep[y];
for(int i = 0;diff > 0 ;++i , diff >>= 1){
if(diff & 1) x = fa[i][x];
}
if(x == y) return x;
for(int i = 19;i >= 0 ; --i)
{
if(fa[i][x] != fa[i][y]){
x = fa[i][x];
y = fa[i][y];
}
}return fa[0][x];
}
bool check(int x,int y,int z)
{
int k = lca(x,z);
return ((lca(x,y) == y) || (lca(y,z) == y)) && lca(y,k) == k;
}
int Val(int x,int y)
{
if(x == y) return 0;
for(int i = 19;i >= 0;i--){
if(dep[fa[i][x]] > dep[y]) x = fa[i][x];
}
return sz[x];
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
for(int i = 1;i < n;i ++){
int x,y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
dep[1] = 0;
fa[0][1] = 0;
dfs(1);
for(int i = 1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
int l = lca(x,y);
if(l == z) cout<<n - Val(x,l) - Val(y,l)<<'\n';
else if(check(x,z,l)) cout<<sz[z] - Val(x,z)<<'\n';
else if(check(y,z,l)) cout<<sz[z] - Val(y,z)<<'\n';
else cout<<"0\n";
}
return 0;
}

浙公网安备 33010602011771号