F. 1-1-1, Free Tree!
链接
思路
思路参考一个博客。原来的思路就是更新对应节点的所有邻接值,然后统一更新。但是复杂度\(O(nq)\)。
注意到:对树每一个节点,仅有一个父节点,那么考虑修改v节点:每次判断其与父节点的路径是否取到;接着对所有子节点进行统一判断,采用map统一管理子节点的值。修改好ans后,只需要修改对应父节点的map和a数组的值。
注意刚开始的\(dfs\)要写成\(dfs(1,0)\),这样不会影响答案。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tin long long
#define itn long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
int a[N];
struct edge
{
int to, val;
edge(int to, int val) {
this->to = to;
this->val = val;
}
edge(){}
};
vector<edge>G[N];
itn fa[N];
int sum[N];
bool vis[N];
int n, q;
int ans;
itn tofaval[N];
map<itn, int>points[N];
void dfs(int now,int father) {
vis[now] = true;
fa[now] = father;
for (edge nex : G[now]) {
itn toer = nex.to, valer = nex.val;
if(toer == father)tofaval[now] = valer;
if (vis[toer])continue;
sum[now] += valer;
if (a[now] != a[toer]) { ans += valer; }
points[now][a[toer]] += valer;
dfs(toer, now);
}
}
void solve() {
cin >> n >> q;
ans = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
vis[i] = 0;
sum[i] = 0;
G[i].clear();
points[i].clear();
}
for (int i = 1; i < n; i++) {
int u, v, w; cin >> u >> v >> w;
G[u].push_back(edge(v, w));
G[v].push_back(edge(u, w));
}
dfs(1, 0);
for (int i = 0; i < q; i++) {
itn v, x; cin >> v >> x;
ans -= (a[fa[v]] != a[v]) ? tofaval[v] : 0;
ans += (a[fa[v]] != x) ? tofaval[v] : 0;
ans -= sum[v] - points[v][a[v]];
ans += sum[v] - points[v][x];
points[fa[v]][a[v]] -= tofaval[v];
points[fa[v]][x] += tofaval[v];
a[v] = x;
cout << ans << '\n';
}
}
signed main() {
IOS;
/**/int t;
cin >> t;
if(t>0)
while (t--)
solve();
return 0;
}