牛客 科大訊飛杯 G題血壓遊戲(虛樹 dp)

2022-05-03 10:15:27 字數 1791 閱讀 3639

題意很好理解。而且很容易發現樹中同一深度的松鼠才會打架。

預處理出節點的深度和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 long

long

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用前面的...