傳送門
一道不錯的題
首先,要知道乙個東西,即若兩條路徑相交,則一條路徑的 lca
lcalc
a 必然在另一條路徑上
我們每加入一條邊,都計算一下之前的邊加上它對答案的貢獻
現在假設加 (a,
b)(a,b)
(a,b
) 條邊,具體有一下幾種情況:
統計 (a,
b)(a,b)
(a,b
) 這條路徑上的 lca
lcalc
a 個數:
大致長這樣:
我們給每個點乙個點權,代表從這個點到根路徑上的 lca
lcalc
a 數量(記為 num
inum_i
numi)
那麼最後的答案顯然是 num
a+nu
mb−2
∗num
lcanum_a+num_b-2*num_
numa+
numb
−2∗
numl
ca每次做完更新的時候,要在 lca
lcalc
a 的子樹內的 num
+1num+1
num+
1,代表它們到根的 lca
lcalc
a 數量多了乙個(就是 lca
lcalc
a)怎麼維護這個 num
numnu
m 呢?可以用乙個區間修改,單點查詢的樹狀陣列來維護(畢竟**量小,常數也小)
統計穿過 (a,
b)(a,b)
(a,b
) 的 lca
lcalc
a 的路徑數量:
大概長這樣:
利用類似於樹上差分的思想,在兩個端點加一,在 lca
lcalc
a 處減二
這樣做之後,把乙個子樹內的值統計出來,就是穿過 lca
lcalc
a 的路徑的數量
因為,如果一條路徑在 (a,
b)(a,b)
(a,b
) 內部,或者在外面(就是不相交的情況),那麼它的值就會被抵消掉(1+1
−21+1-2
1+1−2)
而只有這種乙個點在內部,lca
lcalc
a 和另乙個點在外部的情況(也就是合法情況)才會被統計到
那麼這個又怎麼維護呢?用乙個單點修改,區間查詢的樹狀陣列就行了
一些要注意的細節:
兩個樹狀陣列維護的是不一樣的東西,不要弄混了
注意 lca
lcalc
a 重複的情況要單獨計算,不然會重複(以上兩種方法都會算一次)
#include
#include
#include
#define n 1000005
#define m 2000005
#define lowbit(x) x&-x
using
namespace std;
int n,m,t,tot;
int first[n]
,v[m]
,nxt[m]
;int num[n]
,bit1[n]
,bit2[n]
;int dep[n]
,size[n]
,pos[n]
,fa[n][25
];void
add(
int x,
int y)
void
dfs(
int x)}}
intlca
(int x,
int y)
void
modify
(int
*bit,
int i,
int x)
}int
query
(int
*bit,
int i)
return ans;
}int
main()
dep[1]
=1,dfs(1
);long
long ans=0;
for(i=
1;i<=m;
++i)
printf
("%lld"
,ans)
;// fclose(stdin);
// fclose(stdout);
return0;
}
2019 03 02測試T3 層流
傳送門 題目描述 對於乙個全集 u uu,對於他的兩個子集 a,b a,ba,b,如果 a b a subset b a b 或 b a b ab a 或 a b a b varnothing a b 則這兩個集合就是 u uu 的層流集。現在小 z 想把這個問題搬到樹上來。他給出 n nn 個頂點...
2019 03 30測試T3 里程表
傳送門 題目描述 農民約翰的牛正開始乙個美妙的旅程。牛車的里程表上顯示乙個整數表示里程,旅程開始時里程數為 x 100 x 1018 x 100 le x le 10 x 100 x 10 18 結束時里程數為 y x y 1 018 y x le y le 10 y x y 1018 每當里程表顯...
T3進銷存公升級T 備忘
t3進銷存資料公升級t 只能公升級各種基礎檔案和截至某月底的結存數量 不含單價 金額 一 安裝及加密識別 1.1 因為不能公升級歷史業務單據,所以如果要查詢t3的歷史資料,需要在訂購t 時同時訂購t3查詢工具。1.2 t3和t 需要安裝在一台電腦,t3主要查詢,不再做新資料,所以想用高版本sql,也...