2018 11 05測試T3 相交

2021-08-31 01:25:36 字數 2544 閱讀 8661

傳送門

一道不錯的題

首先,要知道乙個東西,即若兩條路徑相交,則一條路徑的 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,也...