P10930 异象石 题解
P10930 异象石 题解
思路分析
这题是让我们维护一个动态的树上路径并。
首先,树上路径并我们可以用虚树来求,所以如果有部分分的话,可以暴力建虚树来处理。
假设我们要求的虚树上的路径点集按照 DFS 序排好序后为 \(\{ a_i \}_1^n\),那么我们所求的值即为:
\[\frac{\sum_{i=1}^{n}dis(a_i,a_{((i+1) \bmod n)+1})}2
\]
但是直接这么做非常麻烦,我们把式子化简一下:
\[\begin{aligned}
\frac{\sum_{i=1}^{n}dis(a_i,a_{((i+1) \bmod n)+1})}2
& = \frac{\sum_{i=1}^{n}dis_{a_i}+dis_{a_{((i+1) \bmod n)+1}}-2dis_{lca(a_i,a_{((i+1) \bmod n)+1})}}2 \\
& = \sum_{i=1}^n dis_{a_i} - \sum_{i=1}^{n} dis_{lca(a_i,a_{((i+1) \bmod n)+1})}
\end{aligned}
\]
那么剩下的就非常简单了,用一个 set<int> 实现动态维护即可。
CODE
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[i=(g)[i].nxt].v)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
using namespace std;
constexpr int N=1e5+10,lN=17,lV=lN+1;
namespace Tree {
int n,idx;
int dl[N],Lg[N],dep[N],dfn[N];
int dlca[N][lV];
ll dis[N];
template<const int N,const int M>struct CFS {
int tot,h[N];
struct edge {
int v,w,nxt;
edge(int v=0,int w=0,int nxt=-1):v(v),w(w),nxt(nxt) {}
} e[M];
edge &operator[](int i) {
return e[i];
}
void Init(int n) {
tot=-1,RCL(h+1,-1,int,n);
}
void att(int u,int v,int w) {
e[++tot]=edge(v,w,h[u]),h[u]=tot;
}
void con(int u,int v,int w) {
att(u,v,w),att(v,u,w);
}
};
CFS<N,N<<1> g;
void dfs(int u,int fa) {
dep[dfn[dl[u]=++idx]=u]=dep[fa]+1,dlca[dl[u]][0]=fa;
EDGE(g,i,u,v)if(v^fa)dis[v]=dis[u]+g[i].w,dfs(v,u);
}
int dmin(int u,int v) {
return dl[u]<dl[v]?u:v;
}
int lca(int u,int v) {
if(u==v)return u;
if((u=dl[u])>(v=dl[v]))swap(u,v);
int x=Lg[v-u++];
return dmin(dlca[u][x],dlca[v-(1<<x)+1][x]);
}
void Build() {
cin>>n,g.Init(n),Lg[0]=-1;
FOR(i,1,n)Lg[i]=Lg[i>>1]+1;
FOR(i,2,n) {
int u,v,w;
cin>>u>>v>>w,g.con(u,v,w);
}
dfs(1,0);
FOR(j,1,lN)FOR(i,1,n-(1<<j)+1)dlca[i][j]=dmin(dlca[i][j-1],dlca[i+(1<<(j-1))][j-1]);
}
} using namespace Tree;
namespace VT {
int Q;
ll sum;
set<int> st;
int Pre(int u) {
if(st.empty())return dfn[u];
auto it=st.lower_bound(u);
return dfn[it==st.begin()?*st.rbegin():*--it];
}
int Nxt(int u) {
if(st.empty())return dfn[u];
auto it=st.upper_bound(u);
return dfn[it==st.end()?*st.begin():*it];
}
void Insert(int u) {
int pre(Pre(dl[u])),nxt(Nxt(dl[u]));
sum+=dis[u]-dis[lca(pre,u)]-dis[lca(u,nxt)]+dis[lca(pre,nxt)],st.insert(dl[u]);
}
void Erase(int u) {
st.erase(dl[u]);
int pre(Pre(dl[u])),nxt(Nxt(dl[u]));
sum-=dis[u]-dis[lca(pre,u)]-dis[lca(u,nxt)]+dis[lca(pre,nxt)];
}
void Operate() {
for(cin>>Q; Q; --Q) {
char opt;
int u;
cin>>opt;
if(opt=='+')cin>>u,Insert(u);
else if(opt=='-')cin>>u,Erase(u);
else cout<<sum<<endl;
}
}
} using namespace VT;
signed main() {
Build(),Operate();
return 0;
}

浙公网安备 33010602011771号