专栏文章

10.6 测试

算法·理论参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minoc8d5
此快照首次捕获于
2025/12/02 05:41
3 个月前
此快照最后确认于
2025/12/02 05:41
3 个月前
查看原文

T1 U432142 ૮(˶ᵔ ᵕ ᵔ˶)ა祖孙询问

m次询问每次计算x与y的lca,若x=lca(x,y),输出1;y=lca(x,y),输出2;否则输出0
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn(4e4+10);
int n,m,root;
int dep[maxn],dp[maxn][31];
vector<vector<int>>e(maxn);
void dfs(int u,int f){
	dep[u]=dep[f]+1;
	for(int i(0);i<e[u].size();i++){
		int v(e[u][i]);
		if(v==f){
			continue;
		}
		dp[v][0]=u;
		for(int i(1);i<=20;i++){
			dp[v][i]=dp[dp[v][i-1]][i-1];
		}
		dfs(v,u);
	}
}
int LCA(int x,int y){
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	for(int i(20);i>=0;i--){
		if(dep[dp[y][i]]>=dep[x]){
			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];
} 
int main(){
//	freopen("T1.in","r",stdin);
//	freopen("T1.out","w",stdout);
	cin>>n;
	for(int i(1);i<=n;i++){
		int u,v;
		cin>>u>>v;
		if(v!=-1){
			e[u].push_back(v);e[v].push_back(u);
		}else{
			root=u;
		}
	}
	dfs(root,0);
	cin>>m;
	while(m--){
		int x,y;
		cin>>x>>y;
		if(LCA(x,y)==x){
			cout<<"1\n";
		}else if(LCA(x,y)==y){
			cout<<"2\n";
		}else{
			cout<<"0\n";
		}
	}
	return 0;
}

T2 P4281 [AHOI2008] 紧急集合 / 聚会

问:每次询问求x,y,z到某一点汇合的最短路径
对于每次询问的x,y,z,我们发现x,y,z汇合的点时x,y,z的其中一个lca
而另外两个lca相等时,唯一一个不同的lca就是等待点,因为
而最终答案=dis(a,b)+dis(b,c)+dis(a,c)÷2dis(a,b)+dis(b,c)+dis(a,c)\div 2
继续化简,可以得到:
depa+depb2×deplca(a,b)+depb+depc2×deplca(b,c)+depa+depc2×deplca(a,c)÷2=depa+depb+depcdeplca(a,b)deplca(b,c)deplca(a,c)dep_a+dep_b-2\times dep_{lca(a,b)}+dep_b+dep_c-2\times dep_{lca(b,c)}+dep_a+dep_c-2\times dep_{lca(a, c)}\div 2\\=\\dep_a+dep_b+dep_c-dep_{lca(a, b)}-dep_{lca(b,c)}-dep_{lca(a,c)} CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn(5e5+10);
int n,m,root;
bool vis[maxn];
int dep[maxn],dp[maxn][21];
vector<vector<int>>e(maxn);
void dfs(int u,int f){
	dep[u]=dep[f]+1;
	for(int i(0);i<e[u].size();i++){
		int v(e[u][i]);
		if(v==f){
			continue;
		}
		dp[v][0]=u;
		for(int i(1);i<=20;i++){
			dp[v][i]=dp[dp[v][i-1]][i-1];
		}
		dfs(v,u);
	}
}
int LCA(int x,int y){
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	for(int i(20);i>=0;i--){
		if(dep[dp[y][i]]>=dep[x]){
			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];
} 
int BFS(int su,int x,int y,int z){
	int ans(0);
	queue<pair<int,int>>q;
	q.push({su,0});
	vis[su]=true;
	while(q.size()){
		pair<int,int>now(q.front());
		q.pop();
		if(now.first==x||now.first==y||now.first==z){
			ans+=now.second;
		}
		for(int i(0);i<e[now.first].size();i++){
			if(vis[e[now.first][i]]){
				continue;
			}
			vis[e[now.first][i]]=true;
			q.push({e[now.first][i],now.second+1});
		}
	}
	return ans;
}
int main(){
	cin>>n>>m;
	for(int i(1);i<n;i++){
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(1,0);
	for(int i(1);i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		int lca1(LCA(x,y)),lca2(LCA(y,z)),lca3(LCA(x,z));
		int minn(dep[x]+dep[y]+dep[z]-dep[lca1]-dep[lca2]-dep[lca3]);
		if(lca3==lca2){
			cout<<lca1<<' ';
		}else if(lca1==lca3){
			cout<<lca2<<' ';
		}else if(lca1==lca2){
			cout<<lca3<<' ';
		}
		cout<<minn<<'\n';
	}
	return 0;
}

T3 P11477 [COCI 2024/2025 #3] 林卡树 / Stablo

CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5 + 7;
int val[maxn], p[maxn], dep[maxn];
int dp[maxn][22];
int siz[maxn], f[maxn];
vector<int> G[maxn];
void dfs(int u, int fa)
{
    siz[u] = val[u];
    dp[u][0] = fa;
    dep[u] = dep[fa] + 1;
    for (int i = 1; i <= 20; i++)
    {
        dp[u][i] = dp[dp[u][i - 1]][i - 1];
    }
    for (int v : G[u])
    {
        if (v != fa)
        {
            dfs(v, u);
            siz[u] += siz[v];
            f[u] += f[v];
        }
    }
    f[u] += (siz[u] - val[u]);
}
int solve(int x, int y)
{
    for (int i = 20; i >= 0; i--) // 跳到的是大于的最后一个
    {
        if (dep[dp[x][i]] > dep[y]) // 说明深度还没有找到
        {
            x = dp[x][i];
        }
    }
    return x;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, q;
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
    {
        cin >> val[i];
    }
    for (int i = 2; i <= n; i++)
    {
        cin >> p[i];
        G[i].push_back(p[i]);
        G[p[i]].push_back(i);
    }
    dfs(1, 0);
    while (q--)
    {
        int x, y;
        cin >> x >> y;
        if (p[x] == y) // 说明不存在z
        {
            cout << f[y] << "\n";
            continue;
        }
        int z = solve(x, y);
        cout << f[y] - (dep[x] - dep[y] - 1) * val[x] + (siz[z] - siz[x]) << "\n";
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...