題目大意:
給一顆基環樹,求所有長度大於等於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...