异象石(就是sdio宝藏那题)
题解:
之前这道题写过两次题解了吧。。
实现的时候可以用set<int,cmp>来实现按照dfn排序
代码:
感觉别人的分类讨论比我的简单。。
但我觉得我这个写起来也不烦就不看别人的了。。
看了一下 发现他们是把一个的前驱后继处理为自己 于是就避免了分类讨论(我xxx)
linux复制出来行间距变成两倍了。。
#include <bits/stdc++.h> using namespace std; #define rll ll #define IL inline #define rep(i,h,t) for (rll i=h;i<=t;i++) #define dep(i,t,h) for (rll i=t;i>=h;i--) #define ll long long const ll N=4e5; struct re{ ll a,b,c; }e[N*2]; ll cnt,head[N],l; ll bz[20][N]; ll sum[N]; void arr(ll x,ll y,ll z) { e[++l].a=head[x]; e[l].b=y; e[l].c=z; head[x]=l; } ll dfn[N],dep[N]; void dfs(ll x,ll y) { dfn[x]=++cnt; dep[x]=dep[y]+1; bz[0][x]=y; for (rll u=head[x];u;u=e[u].a) { rll v=e[u].b; if (v!=y) { sum[v]=sum[x]+e[u].c; dfs(v,x); } } } ll lca(ll x,ll y) { if (dep[x]<dep[y]) swap(x,y); dep(i,19,0) if (dep[bz[i][x]]>=dep[y]) x=bz[i][x]; if (x==y) return x; dep(i,19,0) if (bz[i][x]!=bz[i][y]) x=bz[i][x],y=bz[i][y]; return bz[0][x]; } struct cmp{ bool operator () (ll x,ll y) { return dfn[x]<dfn[y]; } }; #define tp set<ll,cmp>::iterator set<ll,cmp> S; tp it,it2,it3; IL tp pre(tp it) { tp it2=it; it2--; return(it2); } IL tp nxt(tp it) { tp it2=it; it2++; return(it2); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); ll n; cin>>n; rep(i,1,n-1) { ll x,y,z; cin>>x>>y>>z; arr(x,y,z); arr(y,x,z); } dfs(1,0); rep(i,1,19) rep(j,1,n) bz[i][j]=bz[i-1][bz[i-1][j]]; ll m; cin>>m; ll ans=0; ll num=0; rep(i,1,m) { char cc; ll x; cin>>cc; if (cc=='+') { cin>>x; num++; ans+=2*sum[x]; it =S.insert(x).first; if (num==1) continue; bool tt=0; if (it==S.begin()) { tt=1; it2=nxt(it); it3=S.end(); it3--; if (num!=2) { ans+=2*sum[lca(*it2,*it3)]; ans-=2*sum[lca(x,*it2)]; ans-=2*sum[lca(x,*it3)]; } else ans-=4*sum[lca(x,*it2)]; } it2=nxt(it); if (!tt&&it2==S.end()) { tt=1; it2=pre(it); it3=S.begin(); if (num!=2) { ans+=2*sum[lca(*it2,*it3)]; ans-=2*sum[lca(x,*it2)]; ans-=2*sum[lca(x,*it3)]; } else ans-=4*sum[lca(x,*it2)]; } if (!tt) { it2=pre(it); it3=nxt(it); ans+=2*sum[lca(*it2,*it3)]; ans-=2*sum[lca(x,*it2)]; ans-=2*sum[lca(x,*it3)]; } } if (cc=='-') { cin>>x; num--; if (!num) { ans=0; S.clear(); continue; } it=S.find(x); ans-=2*sum[x]; bool tt=0; if (it==S.begin()) { tt=1; it2=nxt(it); it3=S.end(); it3--; if (num>=2) { ans-=2*sum[lca(*it2,*it3)]; ans+=2*sum[lca(x,*it2)]; ans+=2*sum[lca(x,*it3)]; } else ans+=4*sum[lca(x,*it3)]; } it2=nxt(it); if (!tt&&it2==S.end()) { tt=1; it2=pre(it); it3=S.begin(); if (num>=2) { ans-=2*sum[lca(*it2,*it3)]; ans+=2*sum[lca(x,*it2)]; ans+=2*sum[lca(x,*it3)]; } else ans+=4*sum[lca(x,*it3)]; } if (!tt) { it2=pre(it); it3=nxt(it); ans-=2*sum[lca(*it2,*it3)]; ans+=2*sum[lca(x,*it2)]; ans+=2*sum[lca(x,*it3)]; } S.erase(x); } if (cc=='?') { if (num<=1) cout<<0<<endl; else cout<<ans/2<<endl; } } return 0; }