lca:异象石(set+dfs序)
题目:https://loj.ac/problem/10132
#include<bits/stdc++.h> using namespace std; int n,m,tot=0,N,k=0,head[5000000]; struct node{ int to,next,w; }e[5000000]; int depth[9000000],grand[2000000][20],c[5000000],num[5990000]; long long d[9000000]; void add(int x,int y,int c) { e[++tot].next=head[x],e[tot].w=c,e[tot].to=y,head[x]=tot; } void init() { N=floor(log(n+0.0)/log(2.0)); depth[1]=1; } void dfs(int x) { num[x]=++k;c[k]=x; for(int i=1;i<=N;i++)grand[x][i]=grand[grand[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(v==grand[x][0])continue; depth[v]=depth[x]+1; grand[v][0]=x; d[v]=d[x]+e[i].w; dfs(v); } } int lca(int a,int b) { if(depth[a]>depth[b]) swap(a,b); for(int i=N;i>=0;i--){ if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a]) b=grand[b][i]; } if(a==b) return a; for(int i=N;i>=0;i--){ if(grand[a][i]!=grand[b][i]){a=grand[a][i],b=grand[b][i];} } return grand[a][0]; } set<int> s; #define Auto set<int>::iterator Auto Left(Auto t) { if(t==s.begin()) return --s.end(); return --t; } Auto Right(Auto t) { if(t==--s.end()) return s.begin(); return ++t; } long long dist(int x,int y) { return d[x]+d[y]-(d[lca(x,y)]<<1); } int main() { char ch[10]; scanf("%d",&n); for(int i=1;i<n;i++) { int x,y,z;scanf("%d%d%d",&x,&y,&z); add(x,y,z),add(y,x,z); } init(); dfs(1); scanf("%d",&m); Auto l,r; long long ans=0; for(int i=1;i<=m;i++){ scanf("%s",ch); if(ch[0]=='?') printf("%lld\n",ans>>1); else{ int x; scanf("%d",&x); if(ch[0]=='+') { if(!s.empty()) { r=s.lower_bound(num[x]); if(r==s.end())r=s.begin(); l=Left(r); ans+=dist(c[*l],x)+dist(x,c[*r])-dist(c[*l],c[*r]); } s.insert(num[x]); } else{ r=s.find(num[x]); l=Left(r);r=Right(r); ans-=dist(c[*l],x)+dist(x,c[*r])-dist(c[*l],c[*r]); s.erase(num[x]); } } } return 0; }