日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SDOI2015 寻宝游戏

發(fā)布時間:2023/12/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SDOI2015 寻宝游戏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

傳送門

這題最關(guān)鍵的一點是要想清楚這個路徑長度是咋算的。
要注意到他是走到所有關(guān)鍵點去取寶藏然后回來。我們假想這些關(guān)鍵點構(gòu)成一棵虛樹,那么這就相當(dāng)于是虛樹上的一個dfsdfsdfs
當(dāng)關(guān)鍵點確定的時候,其實最短路徑長就確定了,也就是在虛樹上從一個點開始dfs直到到回到這個節(jié)點所經(jīng)過的路徑長之和。起點其實無所謂,不選虛樹外面的點就行。

如果我們把虛樹上的點按照dfs序從小到大排為p1,p2,?,pnp_1,p_2,\cdots,p_np1?,p2?,?,pn?,那么這時候詢問的答案即為:
ans=∑i=1n?1dis(pi,pi+1)+dis(pn,p1)ans=\sum_{i=1}^{n-1} {dis(p_i,p_{i+1})}+dis(p_n,p_1)ans=i=1n?1?dis(pi?,pi+1?)+dis(pn?,p1?)
算是計算樹上路徑和的一種套路吧。
dfsdfsdfs序從小到大排列,可以想象成是一個環(huán),要求支持在這個環(huán)上加點,刪點,求權(quán)值和。
發(fā)現(xiàn)這個東西用setsetset維護就行了。每次找到前驅(qū)后繼把權(quán)值改一改即可。要注意一下插入的是dfsdfsdfs序。

#include<bits/stdc++.h> #define cs const #define re register #define ll long long cs int N=1e5+10,Log=17; int Head[N],Next[N<<1],V[N<<1],cnt=0; int dfn[N],t[N],key[N],dep[N],f[N][Log],tot=0; int n,m,x,y,pos;ll z,W[N<<1],dis[N]; std::set<int> S; typedef std::set<int>::iterator It; namespace IO{cs int Rlen=1<<22|1;char buf[Rlen],*p1,*p2;inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}template<typename T>inline T get(){char ch;T x;while(!isdigit(ch=gc()));x=ch^48;while(isdigit(ch=gc())) x=((x+(x<<2))<<1)+(ch^48);return x;}inline int gi(){return get<int>();}inline ll gl(){return get<ll>();} } using namespace IO; inline void add(int u,int v,ll w){Next[++cnt]=Head[u],V[cnt]=v,W[cnt]=w,Head[u]=cnt;} inline void dfs(int u,int fa){t[dfn[u]=++tot]=u,f[u][0]=fa,dep[u]=dep[fa]+1;for(int re i=1;i<Log;++i) f[u][i]=f[f[u][i-1]][i-1];for(int re i=Head[u],v=V[i];i;v=V[i=Next[i]])if(v!=fa) dis[v]=dis[u]+W[i],dfs(v,u); } inline int lca(int u,int v){if(dep[u]<dep[v]) std::swap(u,v);for(int re i=Log-1;~i;--i) if(dep[f[u][i]]>=dep[v]) u=f[u][i];if(u==v) return u;for(int re i=Log-1;~i;--i) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];return f[u][0]; } inline ll dist(int u,int v){return dis[u]+dis[v]-2ll*dis[lca(u,v)];} inline int pre(int u){It p=S.lower_bound(u);if(p==S.begin()) return t[*--S.end()];return t[*--p]; } inline int nxt(int u){It p=S.lower_bound(u);if(++p==S.end()) return t[*S.begin()];return t[*p]; } ll ans=0; int main(){ // freopen("2704.in","r",stdin);n=gi(),m=gi();for(int re i=1;i<n;++i)x=gi(),y=gi(),z=gl(),add(x,y,z),add(y,x,z);dfs(1,0);while(m--){pos=gi();if(!key[pos]){key[pos]^=1,S.insert(dfn[pos]),x=pre(dfn[pos]),y=nxt(dfn[pos]);ans+=dist(x,pos)+dist(y,pos)-dist(x,y);}else{key[pos]^=1,x=pre(dfn[pos]),y=nxt(dfn[pos]);ans-=dist(x,pos)+dist(y,pos)-dist(x,y);S.erase(dfn[pos]);}printf("%lld\n",ans);} }

總結(jié)

以上是生活随笔為你收集整理的SDOI2015 寻宝游戏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。