NOIP模擬賽 異象石

2022-07-26 18:30:17 字數 3300 閱讀 8241

adera是microsoft應用商店中的一款解謎遊戲。

異象石是進入adera中異時空的引導物,在adera的異時空中有一張地圖。這張地圖上有n個點,有n-1條雙向邊把它們連通起來。起初地圖上沒有任何異象石,在接下來的m個時刻中,每個時刻會發生以下三種型別的事件之一:

1.地圖的某個點上出現了異象石(已經出現的不會再次出現);

2.地圖某個點上的異象石被摧毀(不會摧毀沒有異象石的點);

3.向玩家詢問使所有異象石所在的點連通的邊集的總長度最小是多少。

請你作為玩家回答這些問題。

第一行有乙個整數n,表示點的個數。

接下來n-1行每行三個整數x,y,z,表示點x和y之間有一條長度為z的雙向邊。

第n+1行有乙個正整數m。

接下來m行每行是乙個事件,事件是以下三種格式之一:

?表示詢問使當前所有異象石所在的點連通所需的邊集的總長度最小是多少。

對於每個 ?事件,輸出乙個整數表示答案。

6

1 2 1

1 3 5

4 1 7

4 5 3

6 4 2

10+ 3

+ 1?

+ 6?

+ 5?

- 6- 3

?

5

1417

10

資料範圍與約定

對於30%的資料,1 ≤ n, m ≤ 1000。

對於另20%的資料,地圖是一條鏈,或者一朵菊花。

對於100%的資料,1 ≤ n, m ≤ 10^5, 1 ≤ x, y ≤ n, x ≠ y, 1 ≤ z ≤ 10^9。

solution

霧。一道很巧妙的思維題。廢話不多說,上題解。

題目大意就是,給一棵樹,要求動態維護乙個值:使所選出的點連通的邊的最小權值和(最小的意思就是不需要更多的邊,已經達到連通狀態,因為是樹,所以這個邊集是唯一的)。有加入和刪除所選定的點的操作。

如圖,對於當前這棵樹:

我們選擇的節點為圖中標號1、2、

3的三個節點,那麼

√標註的邊的權值和就是我們所求的。設

lca(a, b)

為a,b

到兩個點最近公共祖先的路徑長度之和。那麼,這些邊的權值和就是

(lca(1,2)+lca(2,3)+lca(3,1))/2

。並發現這個和是這樣子的:

這一圈,就是尋寶遊戲的答案,就是異象石的答案乘以2的結果。可以想到,對於這樣的點集,要求的這個「圈

」,可以通過兩兩點之間的

lca加和得到。對於乙個點的序列

a[1]~a[i]

,就是lca(a[1],a[2])+lca(a[2],a[3])+……+lca(a[i-1],a[i])+lca(a[i],1)

。而這個序列點的順序是什麼?

dfs序。畫一畫圖很容易就明白了。

所以,我們先預處理出這棵樹節點的dfs序的序號(就是在

dfs過程中,這個點是第幾個被訪問到的)。在維護的過程中,假設加入乙個點後,它的位置是

i,那麼對於答案

ans,我們需要做的改變就是

ans += lca(a[i-1],a[i])+lca(a[i],a[i+1])-lca(a[i-1],a[i+1]);

這個也很容易明白吧。相反,如果刪除乙個點,它原本的位置是

i,只需要

ans -= lca(a[i-1],a[i])+lca(a[i],a[i+1])-lca(a[i-1],a[i+1]);

【切記不要每次修改只搞乙個

bool

陣列記錄而每次詢問都全部重新計算,而是要動態維護

ans】

那麼用什麼來做到維護a序列呢?

stl裡的

set就可以。

s.insert(x);插入x

, s.erase(x);刪除x

, s.lower_bound(x);

返回乙個迭代器,指向集合中第乙個大於或等於

x的元素。集合鍵值就是

dfs序的編號,用這些函式就可以維護

a序列,並且求出

a[i],a[i-1],a[i+1]

是哪些節點。

然而本蒟蒻似乎一時腦抽打了splay。。。。。。

#include#define ll long longinline 

void swap(int &a,int &b)

ll ans,dis[

100024

];int n,m,index,dfn[100024],rank[100024

];int f[100024][18],dep[100024

];int root,cnt,num[100024],son[100024][2],fa[100024

];int head[100024

],ecnt;

struct kokoe[200056

];inline

void add(int u,int v,int

d)inline

void add(int fa,int num,int pd)

inline

int min(int x)

inline

int max(int x)

inline

void dfs(int u,int

fa)inline

int lca(int u,int

v)inline

void rotate(intx)}

inline

void splay(int

x)inline

void splay(int

x)inline ll calc(

int u,int

v)inline

void insert(int

x)inline

int find(intx)}

inline

void delete(int

x)

if(son[x][0])

else

if(son[x][1])

son[fa[x]][num[fa[x]]0;

fa[x]=0; son[x][0]=son[x][1]=0;}

intmain()

return0;

}

異象石 引理證明

adera是microsoft應用商店中的一款解謎遊戲。異象石是進入adera中異時空的引導物,在adera的異時空中有一張地圖。這張地圖上有n個點,有n 1條雙向邊把它們連通起來。起初地圖上沒有任何異象石,在接下來的m個時刻中,每個時刻會發生以下三種型別的事件之一 地圖的某個點上出現了異象石 已經...

Loj題解 10132 異象石

目錄給定一棵 n 個結點的樹,邊有邊權,三種操作 乙個很神奇的結論 記乙個陣列 dfn 用來存dfs序的每個節點 設現有的被標記的點的dfs序從小到大排序後的集合為 設兩個點 u,v 的距離為 dis 那麼答案為 dis dis dis x k dis 的一半 那麼我們用乙個資料結構維護標記的點的序...

刷題 LCA set 異象石

被指標折磨得死去活來.所以這裡具體分析指標 題目描述 adera 是 microsoft 應用商店中的一款解謎遊戲。異象石是進入 adera 中異時空的引導物,在 adera 的異時空中有一張地圖。這張地圖上 有 n 個點,有 n 1 條雙向邊把它們連通起來。起初地圖上沒有任何異象石,在接下來的 m...