代码已过样例但是测试点全wa
小C树由 n 个节点和 n−1 条边构成,节点编号分别为 1,2,...,n,每个节点的初始权值分别为 v1,v2,...,vn。
随后小C会进行 m 次操作,操作共分三种:
1 x
,删除第 x 条输入的边;2 x y
,将编号为 x 的点的权值修改为 y;3 x
,查询编号为 x 的点所在树的权值之和并输出。请你编写程序帮助小C计算并输出每次查询的结果。
输入的第一行,包含两个整数 n,m,分别表示树中点的数量和操作的次数。
输入的第二行,包含 n 个整数,其中第 i 个整数表示树中编号为 i 的节点的初始权值 vi。
接下来 n−1 行,每行包含两个整数,表示树中一条边的两个端点。
最后 m 行,每行依次表示一次操作的信息,具体操作请见题目描述。
对于每个查询操作,输出一行包含一个整数,表示查询的结果。
2 3
1 1
1 2
2 2 4
1 1
3 2
4
1≤n,m≤105
1≤vi,y≤1000
所有操作中,点和边的编号保证合法。
#include <bits/stdc++.h>
using namespace std;
#define DEBUG 0
struct Node{
int father,treevalue,nodevalue;
};
struct Edge{
int u,v;
};
vector<Node> tree;
vector<Edge> edges;
int findroot(int n){//找根
if(tree[n].father==0){
return n;
}
return findroot(tree[n].father);
}
void changevalue(int n,int value){//改点权
tree[n].treevalue+=value;
if(tree[n].father!=0){
changevalue(tree[n].father,value);
}
}
void breakedge(int u,int v){//删边
changevalue(u,-tree[v].treevalue);
tree[v].father=0;
}
int sumtree(int n){//求点权和
if(tree[n].father==0){
return tree[n].treevalue;
}
return sumtree(tree[n].father);
}
int n,m,act,u,v,w;
void rtree(){
for(int i=1;i<=n;i++){
cout<<tree[i].father<<" "<<tree[i].treevalue<<" "<<tree[i].nodevalue<<endl;
}
}
int main(){
cin>>n>>m;
tree.resize(n+1);
edges.resize(n);
for(int i=1;i<=n;i++){
cin>>tree[i].nodevalue;
}
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
tree[b].father=a;
edges.push_back({a,b});
changevalue(a,tree[b].nodevalue);
}
if(DEBUG) rtree();
for(int i=0;i<m;i++){
cin>>act;
if(act==1){
cin>>w;
u=edges[w].u;
v=edges[w].v;
breakedge(u,v);
}
else if(act==2){
cin>>u>>w;
changevalue(u,w-tree[u].nodevalue);
tree[u].nodevalue=w;
}
else if(act==3){
cin>>u;
cout<<sumtree(u)<<endl;
}
if(DEBUG) rtree();
}
return 0;
}