題意很好理解。而且很容易發現樹中同一深度的松鼠才會打架。
預處理出節點的深度和dfs序,然後列舉樹的深度,同一深度的所有節點和根節點s去建虛樹,每建好一次就從根節點s出發跑一次樹型dp
dp的轉移方程比較好想,設當前節點為x,si為x的子樹,則dp[x] = ∑max(1,dp[si] + (depth[si] - depth[x]) ) (dp[si]需要》0)
depth表示節點在原樹的深度,最終每棵虛樹對答案的貢獻是 max(1,dp[x] - 1 )(dp[x]>0)
複雜度o(nlogn)
1 #include2 typedef longlong
ll;3
using
namespace
std;
4const
int maxbit = 20;5
const
int maxn = 2e5+5
;6 vector g[maxn],vt[maxn],p[maxn];//
vt為虛樹
7ll a[maxn],dp[maxn];
8int depth[maxn],fa[maxn][maxbit],log[maxn],in[maxn];//
in陣列為dfs序
9int
n,cnt,s;
10void add(int u,int
v)11
bool cmp(int u,int v)
12void
pre()
17void dfs(int cur,int father)
24for(int i = 0;i)28}
29}30int lca(int u,int
v)36
if(u == v) return u;//
如果u倍增到v,說明v是u的lca
37for(int i = log[depth[u]];i>=0;i--)42}
43return fa[u][0];//
最終結果為u v向上一層就是lca44}
4546
void build (int indx)
59if(st.empty() || st.top()!=cur)
63if(tmp) vt[st.top()].push_back(tmp);//
把最後的tmp節點加入鏈中
64 st.push(p[indx][i]);//
當前p[i]入棧
65vt[p[indx][i]].clear();66}
67 tmp = 0;68
while(!st.empty())73}
74void getdp(int cur)
80for(int i = 0;i)86}
87}88int
main()
93for (int i = 0; i < n-1; ++i)
94100
pre();
101 dfs(s,0
);102 ll ans = 0
;103
if(a[s]>1) ans+=(a[s]-1
);104
else ans+=a[s];
105for(int i = 1;i<=n;i++) p[depth[i]].push_back(i);
106for(int i = 2;i<=n;i++)
116 printf("
%lld
",ans);
117return0;
118 }
血壓遊戲 科大訊飛杯G題 虛樹
一開始的時候,我往長鏈剖分上去寫,但是寫不好,最後寫成了當只有一條鏈的時候是 然後,開始想別的想法了,於是想 到了虛樹的做法。因為,我們可以發現,乙個點,向上影響的時候,只有同等深度的才會同時起作用,只要不是同等深度的時候,那麼他們的時間就會是錯開的,所以,我們可以對深度來進行處理。只有發生這種情況...
牛客科大訊飛杯 日期小助手 暴力模擬
乙個很有趣的模擬題 給你乙個日期,問你最近的後面乙個母親節或父親節是什麼時候。可以看到資料範圍只有一百年,也就是100 365 100組資料,顯然可以暴力。先打出這一百年裡邊的母親節和父親節的表,然後每次輸入乙個日期,暴力 判斷即可。include include include include i...
科大訊飛杯 A 張老師和菜哭武的遊戲
官方題解 其中p xa yb是因為 剛開始遊戲時只有兩個數 乙個a 乙個b 如果遊戲繼續下去 又會挑選下乙個數 要麼是 a b 要麼是a b 或者b a b a 如果我們令下乙個數c a b或者b a 那麼如果遊戲繼續 下乙個要挑選的數就是 c a a c b c c b這幾種情況 如果把c用前面的...