BZOJ3697 採藥人的路徑 點分治

2022-09-14 16:21:20 字數 1749 閱讀 2150

採藥人的藥田是乙個樹狀結構,每條路徑上都種植著同種藥材。

採藥人以自己對藥材獨到的見解,對每種藥材進行了分類。大致分為兩類,一種是陰性的,一種是陽性的。

採藥人每天都要進行採藥活動。他選擇的路徑是很有講究的,他認為陰陽平衡是很重要的,所以他走的一定是兩種藥材數目相等的路徑。採藥工作是很辛苦的,所以他希望他選出的路徑中有乙個可以作為休息站的節點(不包括起點和終點),滿足起點到休息站和休息站到終點的路徑也是陰陽平衡的。他想知道他一共可以選擇多少種不同的路徑。

第1行包含乙個整數n。

接下來n-1行,每行包含三個整數a_i、b_i和t_i,表示這條路上藥材的型別。

輸出符合採藥人要求的路徑數目。

71 2 0

3 1 1

2 4 0

5 2 0

6 3 1

5 7 1

1我可能學了假的點分治……

用g[i][0…1],f[i][0…1]分別表示

前面幾個子樹以及當前子樹路徑長度和為i的路徑數目

0和1用於區分路徑上是否存在字首和為i的節點(也就是可以設立中轉站的節點)

那麼當前子樹的貢獻就是f[0][0] * g[0][0] + σf [i][0] * g [-i][1] + f[i][1] * g[-i][0] + f[i][1] * g[-i][1],

其中i的範圍[-d,d],d為當前子樹的深度。

1 #include2 #include3 #include4

#define n (200000+100)

5using

namespace

std;

6struct

node

7 edge[n*2

];10

intn,k,sum,root,inf;

11long

long ans,g[n][2],f[n][2

];12

int t[n*2

];13

inthead[n],num_edge,max_depth;

14int

depth[n],d[n],size[n],maxn[n],dis[n];

15bool

vis[n];

1617

void add(int u,int v,int

l)18

2425

void get_root(int x,int

fa)26

36 maxn[x]=max(maxn[x],sum-size[x]);

37if (maxn[x]x;38}

3940

void calc(int x,int

fa)41

53 t[dis[x]]--;54}

5556

void solve(int

x)5782}

83for (int i=-up; i<=up; ++i)

84 g[n-i][0]=g[n-i][1]=0;85

for (int i=head[x]; i!=0; i=edge[i].next)

86if (!vis[edge[i].to])

8793}94

95int

main()

96106 get_root(1,0

);107

solve(root);

108 printf("

%lld

",ans);

109 }

BZOJ3697 採藥人的路徑

給定一棵樹,找一些路徑滿足,路徑上0,1數量相等,並在路徑上找到乙個點 休息站 改點到路徑兩端上0,1數量也相等,同一條路徑點不同,記為不同,詢問有多少條路徑滿足條件 點分治 對於乙個點 u 我們遍歷每棵子樹中的節點 v,求出di s u,v 我們記錄這條路徑上有無節點 t 使得di s v,t 0...

bzoj3697 採藥人的路徑

這是個思路題,對我這樣的zz 來說可能已經接近自己想出來的極限了。一看統計符合條件的路徑條數,肯定是點分治,而且肯定是靜態的。首先把邊權變成 1 和 1 那麼一條路徑陰陽平衡也就是說它的權值和等於 0 根據點分治的過程,可知重心和路徑是一對多的關係,而且一條路徑只會對應乙個重心,就是說每條路徑都只會...

bzoj3697 採藥人的路徑

description 採藥人的藥田是乙個樹狀結構,每條路徑上都種植著同種藥材。採藥人以自己對藥材獨到的見解,對每種藥材進行了分類。大致分為兩類,一種是陰性的,一種是陽性的。採藥人每天都要進行採藥活動。他選擇的路徑是很有講究的,他認為陰陽平衡是很重要的,所以他走的一定是兩種藥材數目相等的路徑。採藥工...