BZOJ 4668 -- 冷战 发表于 2019-05-29 | 更新于 2019-06-17 | 分类于 启发式合并 | 评论数: 摘要在线,连接两点,求两点最早何时连接 题面解启发式合并建树 深度 log 暴力求路径最大值 记得维护深度 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081#include <cstdio>#include <algorithm>#include <vector>using std::vector;using std::swap;using std::max;const int MAXN=500011;int N, M;vector<int> Mem[MAXN];int F[MAXN], Size[MAXN], Val[MAXN];int Dep[MAXN];int Cnt;int Ans;int Find(int a){ return a==F[a]?a:Find(F[a]);}void Merge(int a, int b){ a=Find(a);b=Find(b); if(a==b) return; if(Size[a]>Size[b]) swap(a, b); F[a]=b;Val[a]=Cnt;Size[b]+=Size[a]; for(int i=0, s=(int)Mem[a].size(), p;i<s;++i){ p=Mem[a][i]; ++Dep[p]; Mem[b].push_back(p); }}void Ask(int a, int b){ Ans=0; if(Find(a)==Find(b)){ while(a!=b){ if(Dep[a]>Dep[b]) swap(a, b); Ans=max(Ans, Val[b]);b=F[b]; } }}int main(){ scanf("%d%d", &N, &M); for(int i=1;i<=N;++i) {F[i]=i;Size[i]=1;Mem[i].push_back(i);} for(int i=1, t, a, b;i<=M;++i){ scanf("%d%d%d", &t, &a, &b); a^=Ans;b^=Ans; if(t==0){ ++Cnt; Merge(a, b); } else{ Ask(a, b); printf("%d\n", Ans); } } return 0;}/*5 90 1 41 2 50 2 40 3 41 3 10 7 00 6 10 1 61 2 6*/