CF1787G
题意简述
思路
只可惜,一开始还是没有觉得这一点有什么用。
首先很显然可以先预处理把所有好的路径找出来,为了方便用路径的颜色作为它的编号,每次摧毁恢复点只会使一些好的路径出现或消失,而不会改变它们的长度。至于怎么找,可以参考判链的方式,若对于一种颜色
然后就磕死在这里了,如果每次操作记录下每条好的路径的改变情况,那放个菊花图不瞬间复杂度爆炸了……
经wy的点醒:“这是一颗树呀!~”,我脱口而出:“每个节点只有一个爸爸!”
于是发现了关键的突破口,虽然好的路径可能有很多条,但有些路径其实是可以归为一类的。
考虑删掉一个点
可以在每一个节点上开一个
对于摧毁一个点
对于恢复一个点,类似。
但如果直接这样做一条路径可能被删很多次,可以多记录一下除该路径的
细节比较多,写挂了很多次,主要是处理删一个集合和删单条路径的关系时出了些锅(比如删了一个集合就不可能把恢复的路径加入到答案里),所幸靠样例就调出来了。(用
时间复杂度
Code
点击查看代码
#include <bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define l(x) (x<<1) #define r(x) (x<<1|1) #define mpr make_pair //mt19937_64 ra(time(0) ^ (*new char)); //ios::sync_with_stdio(false); //cin.tie(0); cout.tie(0); const ll SIZE = 200005; const ll mod = 998244353; ll n, T; ll head[SIZE], ver[SIZE*2], nxt[SIZE*2], val[SIZE*2], col[SIZE*2], tot; ll len[SIZE], las[SIZE]; ll cnt2[SIZE], cnt1[SIZE], use[SIZE], tt[SIZE], vis[SIZE]; ll id[SIZE]; multiset<ll> s[SIZE], ans; ll gg[SIZE], tag[SIZE]; inline ll rd(){ ll x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = (x<<1) + (x<<3) + (ch^48); ch = getchar(); } return x*f; } void add(ll x, ll y, ll v, ll c){ ver[++tot] = y, nxt[tot] = head[x]; head[x] = tot; val[tot] = v, col[tot] = c; } void dfs(ll x, ll fa, ll fr){ las[x] = fr; for(ll i = head[x]; i; i = nxt[i]){ ll y = ver[i]; tt[col[i]]++; } for(ll i = head[x]; i; i = nxt[i]){ ll y = ver[i]; if(vis[col[i]]) continue; vis[col[i]] = 1; if(tt[col[i]] == 1) cnt1[col[i]]++; else if(tt[col[i]] == 2) cnt2[col[i]]++; else use[i] = 0; } for(ll i = head[x]; i; i = nxt[i]){ ll y = ver[i]; vis[col[i]] = 0, tt[col[i]]--; } for(ll i = head[x]; i; i = nxt[i]){ ll y = ver[i]; if(y == fa) continue; dfs(y, x, col[i]); } } void dfs1(ll x, ll fa){ for(ll i = head[x]; i; i = nxt[i]){ ll y = ver[i]; if(y == fa) continue; if(!vis[col[i]]){ vis[col[i]] = 1; if(use[col[i]]){ id[col[i]] = x; s[x].insert(len[col[i]]); } } dfs1(y, x); } if(!s[x].empty()) ans.insert(*s[x].rbegin()); } int main(){ n = rd(), T = rd(); for(ll i = 1; i < n; i++){ ll x = rd(), y = rd(), v = rd(), c = rd(); add(x, y, v, c); add(y, x, v, c); len[c] += v; use[i] = 1; } use[n] = 1; dfs(1, 0, 0); for(ll i = 1; i <= n; i++){ if(cnt1[i] != 2) use[i] = 0; } dfs1(1, 0); while(T--){ ll tp = rd(), x = rd(); if(tp){ tag[x] = 0; if(!s[x].empty()) ans.insert(*s[x].rbegin()); if(use[las[x]]){ gg[las[x]]--; if(gg[las[x]] == 0){ if(!s[id[las[x]]].empty() && !tag[id[las[x]]]) ans.erase(ans.find(*s[id[las[x]]].rbegin())); s[id[las[x]]].insert(len[las[x]]); if(!tag[id[las[x]]]) ans.insert(*s[id[las[x]]].rbegin()); } } } else{ tag[x] = 1; if(!s[x].empty()) ans.erase(ans.find(*s[x].rbegin())); if(use[las[x]]){ if(gg[las[x]] == 0 && !s[id[las[x]]].empty()){ if(tag[id[las[x]]] == 0) ans.erase(ans.find(*s[id[las[x]]].rbegin())); s[id[las[x]]].erase(s[id[las[x]]].find(len[las[x]])); if(!s[id[las[x]]].empty() && tag[id[las[x]]] == 0) ans.insert(*s[id[las[x]]].rbegin()); } gg[las[x]]++; } } if(!ans.empty()) printf("%lld\n", *ans.rbegin()); else printf("0\n"); } return 0; }
本文作者:Semorius
本文链接:https://www.cnblogs.com/Semorius/p/17538861.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步