Xor Path-lca模板

链接:https://ac.nowcoder.com/acm/contest/3665/C
来源:牛客网
 

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

In graph theory, if an undirected gragh G(V, E) without cycle has n vertices, n − 1 edges and the graph is connected, then G(V, E) is called a tree.
You are given a tree has n vertices, each vertice has a weight. Vertice i's weight is wiw_iwi​
. Henry has q queries, each query has two vertices u, v. He wants to know the xor sum of the weights of all vertices on the shortest path from u to v (contains u,v).

输入描述:

The first line is an integer n(1≤n≤105)n (1 ≤ n ≤ 10^5
)n(1≤n≤105), the number of the vertices.
Line 2 has n integers , the ith integer is wiw_iwi​ (1≤wi≤109)(1 ≤ w_i ≤ 10^9)(1≤wi​≤109)
, the weight of the vertice i.
Line 3 to line n+1, each line has two integers u, v, means there has an edge between u and v(1≤u,v≤n).v (1 ≤ u, v \leq n).v(1≤u,v≤n).
Line n + 1 is q, means the number of queries.
Next q(1≤q≤105)q (1 ≤ q ≤ 10^5
)q(1≤q≤105) lines, each line has two integers u, v (1 ≤ u, v ≤ n) means the beginning and end of
the shortest path henry wants to query.

输出描述:

For each query,output the xor sum of the weights of all vertices on the shortest path from u to v.

示例1

输入

复制

6
1 1 2 3 4 10
1 2
1 3
1 4
2 5
2 6
2
3 6
2 4

输出

复制

8

3

题意:给你一个树求上面的两点的异或路径最短的距离

思路:先从1开始跑全图的点到1异或值用数组记录然后求要求的那两个点的异或值乘以最近公共祖先的异或既是答案

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 500010;
int a[maxn];
struct edge {
    int t, nex;
}e[maxn << 1]; int head[maxn], tot;//零件表建图
int book[maxn];
vector<int>edg[maxn];
void add(int x, int y) {
    e[++tot].t = y;
    e[tot].nex = head[x];
    head[x] = tot;
}//存边
int depth[maxn], fa[maxn][22], lg[maxn];
void dfs(int now, int fath) {
    fa[now][0] = fath; depth[now] = depth[fath] + 1;
    for(int i = 1; i <= lg[depth[now]]; ++i)
        fa[now][i] = fa[fa[now][i-1]][i-1];
    for(int i = head[now]; i; i = e[i].nex)
        if(e[i].t != fath) dfs(e[i].t, now);
}
int LCA(int x, int y) {
    if(depth[x] < depth[y]) swap(x, y);
    while(depth[x] > depth[y])
        x = fa[x][lg[depth[x]-depth[y]] - 1];
    if(x == y) return x;
    for(int k = lg[depth[x]] - 1; k >= 0; --k)
        if(fa[x][k] != fa[y][k])
            x = fa[x][k], y = fa[y][k];
    return fa[x][0];
}//倍增求lca
int b[maxn];
void dfs1(int x) {
	for(int i = 0;i < edg[x].size();++i) {
		if(!book[edg[x][i]]) {
			b[edg[x][i]] = a[edg[x][i]] ^ b[x];
			book[edg[x][i]] = 1;
			dfs1(edg[x][i]);	
		}
	}
}
int main() {
//    int n, m, s; scanf("%d%d%d", &n, &m, &s);
//    for(int i = 1; i <= n-1; ++i) {
//        int x, y; scanf("%d%d", &x, &y);
//        add(x, y); add(y, x);
//    }
//    for(int i = 1; i <= n; ++i)
//        lg[i] = lg[i-1] + (1 << lg[i-1] == i);
//    dfs(s, 0);
//    for(int i = 1; i <= m; ++i) {
//        int x, y; scanf("%d%d",&x, &y);
//        printf("%d\n", LCA(x, y));
//    }
	int n;
	scanf("%d", &n);
	for(int i = 1;i <= n;++i) {
		scanf("%d", &a[i]);
	}
	for(int i = 1; i < n;++i) {
		int u ,v;
		scanf("%d%d", &u, &v);
		add(u, v);add(v, u);
		edg[u].push_back(v);
		edg[v].push_back(u);//先建边
	}
    for(int i = 1; i <= n; ++i) {
    	lg[i] = lg[i-1] + (1 << lg[i-1] == i);
	}
    dfs(1, 0);//倍增求lca求出倍增数组
	b[1] = a[1];book[1] = 1;
	dfs1(1); //求出异或值数组
	int q;
	scanf("%d", &q);
	while(q--) {
		int x, y;
		scanf("%d%d", &x, &y);
		int h = LCA(x, y);//求lca
		printf("%d\n", a[h] ^ b[x] ^ b[y]);
	}
    return 0;
}
发布了219 篇原创文章 · 获赞 43 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_43568078/article/details/104431122
xor