異象石 引理證明

2022-02-15 20:33:03 字數 2820 閱讀 3267

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

異象石是進入adera中異時空的引導物,在adera的異時空中有一張地圖。

這張地圖上有n個點,有n-1條雙向邊把它們連通起來。

起初地圖上沒有任何異象石,在接下來的m個時刻中,每個時刻會發生以下三種型別的事件之一:

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

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

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

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

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

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

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

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

」+ x」 表示點x上出現了異象石

」- x」 表示點x上的異象石被摧毀

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

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

1≤n,m≤10^5,

1≤x,y≤n,

x≠y,

1≤z≤109

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

思路和藍書上一樣, 按dfs序對答案進行修改, 思路就不再說了,

主要說下為什麼 按dfs這樣算 是答案的兩倍

證明(數學歸納法):

設 \(f(x,y)=d[x]+d[y]-2*d[lca(x,y)]\)

當 k = 1, ans=0

當 k = 2, \(ans=f(a_1,a_2)+f(a_2,a_1)\), 答案顯然是兩倍

當 k = 3, \(ans=f(a_1,a_2)+f(a_2,a_3)+f(a_3,a_1)\)

對於n = 2少了個 \(f(a_2,a_1)\), 多了\(f(a_2,a_3)+f(a_3,a_1)\)

即多了 \(2*d[3]+2*d[lca(a_1,a_2)]-2*d[lca(a_2,a_3)]-2*d[lca(a_1,a_3)]\)

我們發現都乘了個 2, 這便是加入a_3之後對答案 兩倍 的影響

由於我們是嚴格按照 dfs序 算的, 所以 a_3 對於 a_2有

1.a_3是a_2的子節點, 那麼剛才一長串就是 a_2到a_1 和 a_2到a_3的距離的兩倍

2.a_3和a_2在不同的兩顆子樹上\([lca(a_2,a_3) \neq a_2]\), 剛才的一長串就是 a_2到a_1 和 a_3到\(lca(a_1,a_2,a_3)\)距離的兩倍

當 k = n, \(ans=\sum_^f(a_1,a_i)+f(a_n,a_1)\), 比 k = n - 1 多出的部分也分為

1.\(a_是a_n\)的子節點, 那麼多出部分為....

2.\(a_和a_n\)在不同的兩顆子樹上\([lca(a_,a_n) \neq a_2]\), 多出的部分為....

就簡單證明一下, 主要不懂引理, 就不會寫(暴力超時), 具體**如下

#pragma gcc optimize(2)

#include #define rep(i, a, b) for (int i = (a); i <= (b); ++i)

#define per(i, a, b) for (int i = (a); i >= (b); --i)

#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

typedef long long ll;

const int n = 1e5 + 5;

struct stfrom

void bfs(int s) }}

int lca(int x, int y)

ll dist(int x, int y)

} st;

int n, m, dfn[n], df;

vector> h[n];

set> st;

long long ans = 0;

void dfs(int x, int fa)

ll get(int x) );

if (it == st.end()) q = st.begin()->second;

else q = it->second;

if (it == st.begin()) p = st.rbegin()->second;

else p = (--it)->second;

return st.dist(p, x) + st.dist(q, x) - st.dist(p, q);

}int main()

st.init(n, h); st.bfs(1); dfs(1, 0);

for (cin >> m; m; --m) );

} else if (op == '-') ));

if (!st.empty()) ans -= get(x);

} else cout << ans / 2 << '\n';

}return 0;

}

Loj題解 10132 異象石

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

NOIP模擬賽 異象石

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

刷題 LCA set 異象石

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