bzoj3648 寢室管理 樹分治

2021-08-02 04:29:38 字數 1698 閱讀 5658

題目大意:

給一顆基環樹,求所有長度大於等於k的路徑。

題目分析:

如果沒有環,只有樹的話,只要裸上樹分治就可以了。

有環的話我們就先把環上的一條邊去掉,然後做樹分治。

這樣我們就統計出了所有不經過這條邊的路徑樹,還剩下所有經過這條邊的路徑數。

我們此時處理出以環上所有點位根的子樹資訊,並將其合併。

然後每次去掉環上乙個點的資訊,再用這個點的子樹資訊與環上其他點的子樹資訊更新答案(通過剛才刪掉那條邊的)。

**如下:

#include 

#include

#include

#include

#define n 120000

using

namespace

std;

typedef

long

long ll;

inline

int lowbit(int x)

int n,m,k,sum,root,rtf;

int fir[n],nes[n<<1],v[n<<1],tot=1;

int fw[n],tim[n],fa[n],son[n],sz[n],sta[n],top;

int time_stamp,cut;

bool mark[n],vis[n];

vector

ring;

ll ans;

void edge(int x,int y)

#define edge(x,y) edge(x,y),edge(y,x)

void update(int x,int v=1)

return;

}int query(int x)

return ans;

}void dfs(int c)

ring.push_back(tmp);

cut=t;

continue;

}fa[v[t]]=c;

dfs(v[t]);

}}void find_focus(int c,int fa)

if(sum-sz[c]>son[c]) son[c]=sum-sz[c];

if(son[c]<=son[root]) root=c,rtf=fa;

}void dfs(int c,int fa,int dep)

}void solve(int c)

for(int t=fir[c];t;t=nes[t])

}int main()

dfs(1);

son[0]=sum=n; root=0;

find_focus(1,0);

sz[rtf]=sum-sz[root];

solve(root);

sum=ring.size();

memset(vis,0,sizeof(vis));

for(int i=0;itrue;

time_stamp++;

for(int i=0;i0;

dfs(ring[i],0,1);

for(int j=1;j<=top;j++)

update(sta[j]+i);

}for(int i=sum-1;i>=0;i--)

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

return

0;}

bzoj3648 寢室管理 環套樹 點分治

題目描述 t64有乙個好朋友,叫t128。t128是寄宿生,並且最近被老師叫過去當宿管了。宿管可不是一件很好做的工作,碰 巧t128有乙個工作上的問題想請t64幫忙解決。t128的寢室條件不是很好,所以沒有很多錢來裝修。禮間寢室僅由n 1條雙向道路連線,而且任意兩間寢室之間都可以互達。最近,t128...

BZOJ3648 寢室管理(點分治 bit)

傳送門 sunshine學長去年的互測題orz 然而他給的solution除了點分和bit什麼都沒說啊。硬著頭皮想吧,反正我知道要用bit了。如果是樹的話點分治 二分或者bit就能搞定 如果是環套樹的話怎麼辦捏 首先考慮不經過環的答案,直接在外向樹上點分就行了 然後考慮經過環的答案 假設當前外向樹上...

bzoj3648 環套樹 點分治 樹狀陣列

tree 1s 128m by hzw czy神犇種了一棵樹,他想知道地球的質量 給定一棵n個點的樹,求樹上經過點的個數 k的路徑數量ans 對於部分資料,樹上某兩點間會多出最多一條無向邊 輸入資料 n,m,k 接下來n行,每行u,v表示u與v間有無向邊連線 輸出資料 ans樣例資料 input 5...