BZOJ3991 尋寶遊戲 LCA 虛樹 SET

2022-09-01 06:21:12 字數 2130 閱讀 6688

小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n-1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小b希望評測一下這個遊戲的難度,因此他需要知道玩家找到所有寶物需要行走的最短路程。但是這個遊戲中寶物經常變化,有時某個村莊中會突然出現寶物,有時某個村莊內的寶物會突然消失,因此小b需要不斷地更新資料,但是小b太懶了,不願意自己計算,因此他向你求助。為了簡化問題,我們認為最開始時所有村莊內均沒有寶物

第一行,兩個整數n、m,其中m為寶物的變動次數。

接下來的n-1行,每行三個整數x、y、z,表示村莊x、y之間有一條長度為z的道路。

接下來的m行,每行乙個整數t,表示乙個寶物變動的操作。若該操作前村莊t內沒有寶物,則操作後村莊內有寶物;若該操作前村莊t內有寶物,則操作後村莊內沒有寶物。

m行,每行乙個整數,其中第i行的整數表示第i次操作之後玩家找到所有寶物需要行走的最短路程。若只有乙個村莊內有寶物,或者所有村莊內都沒有寶物,則輸出0。

4 5

1 2 30

2 3 50

2 4 6023

421

0

100220

220280

1<=n<=100000

1<=m<=100000

對於全部的資料,1<=z<=10^9

其實這題是乙個比較坑爹的題,可以用虛樹做,也可以用set+lca做

這裡講下set+lca的做法

首先我們可以將各個點的dfn值在set中刪除,用dfn是因為set中的元素都是有序的,這樣方便查詢,當然也可以手寫rank_tree(splay,treap等),這樣效率或許更高。

\[insert_(x)=ans_-dis(before,after)+dis(x,before)+dis(x,after)

\]\[erase_(x)=ans_+dis(before,after)-dis(x,before)-dis(x,after)

\]其中dis為

\[dis(x,y)=dis\bigr(lca(x,y),x\bigl)+dis\bigr(lca(x,y),y\bigl)

\]期間我們可以用樹剖求lca,並在樹剖的第乙個dfs裡初始化好各個點到根的距離。

虛樹做法

易知,答案就是各個關鍵點之間形成的樹的邊權和的兩倍,這就是虛樹!對於一顆虛樹,答案就是各個的dfs序排序,相鄰兩點的距離和,再加上最後乙個到第乙個的距離,直接用set維護dfs序就好了,注意最後要減掉所有關鍵點的lca的深度

#include#include#include#includeusing namespace std;

const int n=1000001;

int n,q,tot,root,maxn,dftim,tim[n],fa[n],to[n<<1],nx[n<<1],head[n<<1],dep[n],siz[n],son[n],top[n],dfn[n],dfnnode[n+5];

long long cost[n<<1],ans,toroot[n];

bool flag[n];

sets;

void addedge(int x,int y,long long z)

void dfs1(int u,int f)

}void dfs2(int u,int topf)}

int lca(int x,int y)

dfs1(root,0);

dfs2(root,root);

s.insert(0),s.insert(n+1);

while(q--)else

int first=*++s.find(0),last=*--s.find(n+1);long long hehe=0;

if (first<1 or last>n) hehe=0;

else hehe=get(dfnnode[first],dfnnode[last]);

printf("%lld\n",ans+hehe);

flag[x]=!flag[x];

} return 0;

}

bzoj3991 尋寶遊戲

題目鏈結 題意 給出乙個n個節點的帶權樹,m次操作每次修改乙個關鍵點,求每次操作後,從其中任意乙個關鍵點出發走遍所有關鍵點再走回起點所需的最小花費。solution 假如沒有修改操作的話,就像乙個簡單的在虛樹上樹形dp,方程如下 f i sigma sigma。觀察一下dp的過程,就是不斷地從前面的...

BZOJ3991 尋寶遊戲

小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n 1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小...

尋寶遊戲(bzoj 3991)

小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n 1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小...