Main idea:
Steamed Fish is a dedicated YYH Land forest ranger. He is responsible for daily maintenance of the forest of YYH Land. At the beginning, there was only one tree with nn in YYH LandA tree of n nodes, each node has a spiritual power valuevvv。
Since YYH Land is a magical country, the trees of YYH Land also have some magical abilities. Specifically, it satisfies the following operations:
- 1 e
Numbered eeThe edge of e suddenly disappeared, making the tree it was on into two trees.
- 2 uuu v a l val val
The spiritual power value of the node numbered uu becomes valval.
- 3 uuu
The steamed fish made a query to query the sum of the spiritual power of the tree where uu is located.
Now you need to help steamed fish to simulate the above events to understand the changes in the forest.
Question idea:
See the plus side, the operation minus side, to 并查集
close on it
as this problem is limited to the border erase, and along with the change in the value of the right
is clear that the border erase operation is not good to maintain the value of spiritual power
, however, edging operation for each The change of the spiritual power value of a piece is very easy to maintain.
Assuming that there is only an edge operation, then for a point x's spiritual power value changes, then the root of a point x (and search for the root) increase newval − lastval newval- lastvalnewval−l a s t v a l is all right.
So after considering storing the operation offline, flashback processing (minus side is replaced with added side)
also corresponds to the change of the weight. It is good to
note that before flashback processing, you should save the operation. After the picture权值
and the分块
situation, then operate on this picture, instead of directlynnOperate on n points
Code:
/*** keep hungry and calm CoolGuang! ***/
/*#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)*/
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 4e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int pre[maxn];
ll num[maxn],val[maxn];
pair<int,int>e[maxn];
vector<int>v[maxn];
int vis[maxn];
int Find(int x){
return pre[x]==x?x:pre[x] = Find(pre[x]);
}
struct node{
int op,x,y;
}q[maxn];
ll res[maxn];
int main(){
read(n);read(m);
for(int i=1;i<=n;i++){
read(num[i]);
val[i] = num[i];
pre[i] = i;
v[i].push_back(num[i]);
}
for(int i=1;i<=n-1;i++){
int x,y;read(x);read(y);
e[i] = {
x,y};
}
for(int i=1;i<=m;i++){
read(q[i].op);
if(q[i].op == 1){
read(q[i].x);
vis[q[i].x] = 1;
}
else if(q[i].op == 2){
read(q[i].x);
read(q[i].y);
v[q[i].x].push_back(q[i].y);
}else read(q[i].x);
}
for(int i=1;i<=n;i++)
if(v[i].size())
val[i] = num[i] = v[i].back();
for(int i=1;i<=n-1;i++){
if(vis[i]) continue;
int dx = Find(e[i].first),dy = Find(e[i].second);
if(dx != dy){
pre[dx] = dy;
val[dy] += val[dx];
}
}
for(int i=m;i>=1;i--){
if(q[i].op == 1){
int dx = Find(e[q[i].x].first),dy = Find(e[q[i].x].second);
if(dx != dy){
pre[dx] = dy;
val[dy] += val[dx];
}
}else if(q[i].op == 2){
v[q[i].x].pop_back();
int dx = Find(q[i].x);
val[dx] += v[q[i].x].back() - num[q[i].x];
num[q[i].x] = v[q[i].x].back();
}
else res[i] = val[Find(q[i].x)];
}
for(int i=1;i<=m;i++){
if(res[i])
printf("%lld\n",res[i]);
}
return 0;
}
/***
5 7
1 2 3 4 5
1 2
2 3
3 4
4 5
3 1
3 2
2 1 5
1 2
2 1 3
3 1
3 5
****/