异或和
题目:
思路:
题目要求需要对一个有n
个节点的树进行求异或和,首先输入n
个节点的权值,然后输入边,我们可以使用单向边,因为节点值较小的边不可能是节点值较大的点的子节点,因此我们可以使用一个if
判断进行存放单向边,(存放单向边的一个好处是:在进行深度优先搜索的时候可以不用在判断是否又连接到了父节点)。
一共有m
个操作,对于每一个操作有两种形式,第一种形式是:将点x
的权值赋值为y
【注意:这里不是将x
的权值赋值为y
的权值】,第二种形式是:查询以x
为哦根节点的子树内的所有点权的异或和,这个我们可以通过一个深度优先搜索实现(广度优先搜索也可以)。在进行搜索的时候可以直接进行异或,即将异或的结果作为一个参数进行传递。
代码:
便于理解版本:
// 异或和
#include<iostream>
using namespace std;
#include<vector>
const int N = 1e5 + 100;
vector<int> A(N, 0); // 用于记录各个点的权值
vector<int> edge[N]; // 用于记录边
// 深度优先搜索
int dfs(int u, vector<int> &A, vector<int> edge[N], int &ans){ // 注意参数使用&是有好处的,其中一个好处是节省内存,并且在一定长度上可以节省开辟新内存的时间
if(edge[u].size() == 0) return 0; // 如果该节点的孩子节点是空,即如果该节点是一个叶子节点,就直接退出
// 遍历每一个点的所有子节点
for(unsigned i = 0;i < edge[u].size();i++){
int idx = edge[u][i];
ans ^= A[idx]; // 进行异或
// cout<<ans<<endl;
dfs(edge[u][i], A, edge, ans); // 进行深度优先搜索
}
return 0;
}
void solve(){
int n, m;
cin>>n>>m;
// 进行赋权值
for(int i = 1;i <= n;i ++) cin>>A[i];
int u,v;
// n - 1条边
for(int i = 0;i < n - 1; i++){
cin>>u>>v;
// 进行一次判断,取值较小的点一定不可能是取值较大的点的子节点,因此只需要存单向边即可。
if(u < v) edge[u].push_back(v);
else edge[v].push_back(u);
}
// m次查询
int x,y;
for(int i = 0;i < m; i++){
int ch;
cin>>ch;
// 判断是哪一种情况
if(ch == 1){
cin>>x>>y;
A[x] = y; // 如果是情况一,就直接改变值即可
}else{
cin>>x;
int ans = A[x]; // 使用ans进行记录以x为根节点的所有子节点的异或和
dfs(x, A, edge, ans); // 如果是情况二,就直接进行dfs深度优先搜索,传递参数是:根节点的位置,权值数组,边数组, 异或结果记录值
cout<<ans<<endl;
}
}
return ;
}
int main(){
int t = 1;
while(t--){
solve();
}
return 0;
}
/*
示例:
输入:
4 4
1 2 3 4
1 2
1 3
2 4
2 1
1 1 0
2 1
2 2
输出:
4
5
6
*/
简化版本:
// 异或和
#include<iostream>
using namespace std;
#include<vector>
const int N = 1e5 + 100;
vector<int> A(N, 0);
vector<int> edge[N];
// DFS深度优先搜索
int dfs(int u, int &ans){
if(edge[u].size() == 0) return 0;
for(unsigned i = 0;i < edge[u].size();i++){
ans ^= A[edge[u][i]];
dfs(edge[u][i], ans);
}
return 0;
}
void solve(){
int n, m;
cin>>n>>m;
// 进行赋权值
for(int i = 1;i <= n;i ++) cin>>A[i];
int u,v;
for(int i = 0;i < n - 1; i++){
cin>>u>>v;
if(u < v) edge[u].push_back(v);
else edge[v].push_back(u);
}
// m次查询
int x,y;
for(int i = 0;i < m; i++){
int ch;
cin>>ch;
if(ch){
cin>>x>>y;
A[x] = y;
}else{
cin>>x;
int ans = A[x];
dfs(x, ans);
cout<<ans<<endl;
}
}
return ;
}
int main(){
int t = 1;
while(t--){
solve();
}
return 0;
}