bzoj3697 採藥人的路徑 (點分治)

2021-08-11 07:53:09 字數 1569 閱讀 3519

原題位址

題意:

採藥人的藥田是乙個樹狀結構,每條路徑上種植一種藥,有0/1兩種藥。

草藥人希望選擇一條兩種藥材數目相等的路徑,且選出的路徑中有乙個可以作為休息站的節點(不包括起點和終點),滿足起點到休息站和休息站到終點的路徑也是兩種藥數量相等。

他一共可以選擇多少種不同的路徑。

資料範圍

n ≤ 100,000

題解:

如果把0的藥看做-1,那麼就是選擇一條路徑,他的邊權和為零,且存在乙個點,使分成路徑的兩側邊權和也為零。

1.休息站在一條從根出發的路徑上:

那麼該路徑上存在乙個點,根到他的邊權和與根到端點的邊權和相等。 他可以與其他子樹的邊權和為相反數的路徑組成合法路徑。

2.休息站在根。

兩條不在同一子樹的邊權和為0的路徑互相組合。

於是在點分治時,統計滿足以上的路徑條數。

為了區分子樹,用f,g兩個陣列。

f[i][0/1]表示當前子樹路徑和為i且這條路徑上方是否有過和為i的字首,

g[i][0/1]分別表示之前遍歷的所有子樹路徑和為i且這條路徑上方是否有過和為i的字首,

初值為g[i][0]=1,要考慮到由根節點出發的路徑。

ans+=f[i][1]*(g[-i][0]+g[-i][1])+f[i][0]*g[-i][1]

ans+=f[0][0]*(g[0][0]-1)

清空只清空賦了值的。

**:

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int n=100005;

ll f[2*n][2],g[2*n][2],ans=0,cnt[2*n];

int n,head[n],to[2*n],w[2*n],nxt[2*n],num=0,size[n],ss[n],sz,root=0,dis[n],dep[n],mxdep=0;

bool del[n];

void build(int u,int v,int ww)

void getroot(int u,int f)

ss[u]=max(size[u],sz-size[u]);

if(ss[u]void getdis(int u,int fa)

cnt[dis[u]+n]--;

}ll cal(int u)

}for(int i=-mx;i<=mx;i++)

g[i+n][0]=g[i+n][1]=0;

}void dfs(int x)

}int main()

sz=n; ss[0]=n+10; dfs(1);

printf("%i64d\n",ans);

return

0;}

BZOJ3697 採藥人的路徑

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

bzoj3697 採藥人的路徑

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

bzoj3697 採藥人的路徑

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