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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【SDOI2015】寻宝游戏

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

樣例輸入

4 5
1 2 30
2 3 50
2 4 60
2
3
4
2
1

樣例輸出

0
100
220
220
280

提示

題解

本題不斷增刪關鍵點,而且有一個顯而易見的結論:不管從哪個點出發,每條路徑都會走兩遍。我們可以維護一棵動態虛樹,記錄虛樹中的路徑總長。具體實現需要開一個DFS序的set,增刪點類比建虛樹過程即可。

代碼

#include<stdio.h> #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cmath> #include<set> using namespace std; typedef long long ll; const int maxn=1e5+5; ll a,b,c,n,m,ans,cnt,Last[maxn]; ll vt,lca,id[maxn],dep[maxn],dfn[maxn],dis[maxn],fa[maxn][20]; set<ll> cache; struct node {ll End,Next,Len; }edge[2*maxn]; void save(ll x,ll y,ll z) {edge[++cnt].End=y,edge[cnt].Len=z;edge[cnt].Next=Last[x],Last[x]=cnt; } void DFS(ll x) {dep[x]=dep[fa[x][0]]+1;dfn[x]=++vt,id[vt]=x;ll s=ceil(log2(dep[x]));for(ll i=1;i<=s;i++) fa[x][i]=fa[fa[x][i-1]][i-1];for(ll i=Last[x];i;i=edge[i].Next){ll y=edge[i].End;if(y==fa[x][0]) continue;fa[y][0]=x,dis[y]=dis[x]+edge[i].Len;DFS(y);} } ll getlca(ll x,ll y) {if(dep[x]<dep[y]) swap(x,y);ll k=dep[x]-dep[y],s=ceil(log2(n));for(ll i=0;i<=s;i++)if(k&(1<<i)) x=fa[x][i];if(x==y) return x;k=ceil(log2(dep[x]));for(ll i=k;i>=0;i--)if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0]; } ll pre(ll x) {set<ll>::iterator y=cache.find(dfn[x]);if(y==cache.begin()) return 0;return id[*(--y)]; } ll las(ll x) {set<ll>::iterator y=cache.find(dfn[x]);y++;if(y==cache.end()) return 0;return id[*y]; } void clr(ll x) {ll l=pre(x),r=las(x);if(l) lca=getlca(x,l),ans-=dis[x]+dis[l]-2*dis[lca];if(r) lca=getlca(x,r),ans-=dis[x]+dis[r]-2*dis[lca];if(l&&r) lca=getlca(r,l),ans+=dis[r]+dis[l]-2*dis[lca];cache.erase(dfn[x]); } void ins(ll x) {cache.insert(dfn[x]);ll l=pre(x),r=las(x);if(l) lca=getlca(x,l),ans+=dis[x]+dis[l]-2*dis[lca];if(r) lca=getlca(x,r),ans+=dis[x]+dis[r]-2*dis[lca];if(l&&r) lca=getlca(r,l),ans-=dis[r]+dis[l]-2*dis[lca]; } int main() {scanf("%lld%lld",&n,&m);for(ll i=1;i<n;i++){scanf("%lld%lld%lld",&a,&b,&c);save(a,b,c),save(b,a,c);}DFS(1);while(m--){scanf("%lld",&a);if(!cache.size()) cache.insert(dfn[a]),puts("0");else{if(cache.find(dfn[a])!=cache.end()) clr(a);else ins(a);lca=getlca(id[*cache.begin()],id[*(--cache.end())]);printf("%lld\n",ans+dis[id[*cache.begin()]]+dis[id[*(--cache.end())]]-2*dis[lca]);}}return 0; }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。