bzoj3991 [SDOI2015]寻宝游戏 set
生活随笔
收集整理的這篇文章主要介紹了
bzoj3991 [SDOI2015]寻宝游戏 set
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#Description
小B最近正在玩一個尋寶游戲,這個游戲的地圖中有N個村莊和N-1條道路,并且任何兩個村莊之間有且僅有一條路徑可達。游戲開始時,玩家可以任意選擇一個村莊,瞬間轉移到這個村莊,然后可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物并返回到最初轉移到的村莊為止。小B希望評測一下這個游戲的難度,因此他需要知道玩家找到所有寶物需要行走的最短路程。但是這個游戲中寶物經常變化,有時某個村莊中會突然出現寶物,有時某個村莊內的寶物會突然消失,因此小B需要不斷地更新數據,但是小B太懶了,不愿意自己計算,因此他向你求助。為了簡化問題,我們認為最開始時所有村莊內均沒有寶物
1<=N<=100000
1<=M<=100000
對于全部的數據,1<=z<=10^9
#Solution
今天打noip模擬T3和這個做法好像是類似的,然后我發現這道題之前寫過但是沒有A,現在終于補上了
答案顯然為選中的dfs序相鄰點的距離和(繞,考慮用平衡樹(set)維護這個東西,我們只需要在插入和刪除的時候把貢獻改一下即可
#Code
#include <stdio.h> #include <string.h> #include <algorithm> #include <set> #define rep(i,st,ed) for (int i=st;i<=ed;++i) #define drp(i,st,ed) for (int i=st;i>=ed;--i)typedef long long LL; const int N=200005; const int E=200005;struct edge {int y,w,next;} e[E]; struct data {int fi,se;friend bool operator <(data a,data b) {return (a.fi==b.fi)?(a.se<b.se):(a.fi<b.fi);} };std:: set <data> set; std:: set <data>:: iterator pos;LL dis[N];int dfn[N],dep[N],fa[N][21]; int ls[N],edCnt;bool vis[N];int read() {int x=0,v=1; char ch=getchar();for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());return x*v; }void addEdge(int x,int y,int w) {e[++edCnt]=(edge) {y,w,ls[x]}; ls[x]=edCnt;e[++edCnt]=(edge) {x,w,ls[y]}; ls[y]=edCnt; }void dfs(int now) {dfn[now]=++dfn[0];rep(i,1,20) fa[now][i]=fa[fa[now][i-1]][i-1];for (int i=ls[now];i;i=e[i].next) {if (e[i].y==fa[now][0]) continue;dep[e[i].y]=dep[now]+1;dis[e[i].y]=dis[now]+e[i].w;fa[e[i].y][0]=now;dfs(e[i].y);} }int get_lca(int x,int y) {if (dep[x]<dep[y]) std:: swap(x,y);drp(i,20,0) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];if (x==y) return x;drp(i,20,0) if (fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];}return fa[x][0]; }LL get_dis(int x,int y) {int lca=get_lca(x,y);return dis[x]+dis[y]-2*dis[lca]; }int main(void) {int n,m; scanf("%d%d",&n,&m);rep(i,2,n) {int x=read(),y=read(),w=read();addEdge(x,y,w);}dfs(1); LL ans=0;while (m--) {int x=read(),a=0,b=0,st=1,ed=1; data now={dfn[x],x};vis[x]^=1;if (vis[x]) {set.insert(now); pos=set.find(now);if (set.size()==1) {puts("0");continue;}if (pos!=set.begin()) {pos--; a=(*pos).se;ans+=get_dis(x,a);pos++;}pos++;if (pos!=set.end()) {b=(*pos).se;ans+=get_dis(x,b);}pos--;if (a&&b) ans-=get_dis(a,b);} else {pos=set.find(now);if (set.size()==1) {set.erase(now);puts("0");continue;}if (pos!=set.begin()) {pos--; a=(*pos).se;ans-=get_dis(x,a);pos++;}pos++;if (pos!=set.end()) {b=(*pos).se;ans-=get_dis(x,b);}pos--;if (a&&b) ans+=get_dis(a,b);set.erase(now);}if (set.size()) {pos=set.begin(); st=(*pos).se;pos=set.end(); pos--; ed=(*pos).se;}printf("%lld\n", ans+get_dis(st,ed));}return 0; }總結
以上是生活随笔為你收集整理的bzoj3991 [SDOI2015]寻宝游戏 set的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【自学】张量、维度、多维矩阵、dim、t
- 下一篇: Docker实用指令整理