JZOJ 4211 送你一棵聖誕樹

2021-07-05 04:55:32 字數 3002 閱讀 6201

有n+

1 顆樹,編號為t0

~tn ,對於每一棵樹ti,他在第ta

i 棵樹的第ci

個點和第tb

i 棵樹的第di

個點之間連上了一條長度為le

ni的邊。在ti

中,他保持ta

i 中的所有節點編號不變,把tb

i 中的所有節點的編號加上si

zeai

。 我們定義一棵樹的美觀度為兩兩點之間的距離之和,現在要輸出所有樹的美觀度。

我們可以模擬這個樹的構成過程,然後把他們全部存下來。

對於美觀度暴力遍歷整棵樹,加起來。

這題其實是很隱蔽的搜尋題

仔細想想,這棵樹其實是之前的兩棵樹的組合,我們有必要知道整棵樹嗎?

我們只需要知道是哪顆樹就行了。

我們看當前這棵樹。

我們已知他的左兒子是ta

,右兒子是tb

,連線點是

x ,y,

suma

,sum

b (美觀度),si

zea ,si

zeb (節點數),連線的邊長度為藍色那條邊為le

n 。

我們不妨再設d[

t][i

] 表示第

t 棵樹,編號為

i的節點到整棵樹的距離和。

至此,我們再結合d[

a][x

] ,d[

b][y

] ,我們不難推出su

mi。 問題s

uma ,su

mb是子問題,之前一定會處理過的。

那麼我們剩下的問題就是d[

t][i

] 怎麼求了。

我們設乙個狀態di

s[t]

[i][

j]表示樹

t 裡編號為

i的點到編號

j 的點的距離。

我們可以通過di

s[t]

[i][

j]來在每次合併的時候推出d[

t][i

] d[

t][i

] 就是現在的d[

t][i

] 加上多出來的子樹到其關鍵點的距離和加上le

n 的其si

ze倍再加上自己到自己所在子樹的關鍵點的距離的si

ze倍。

比較繞口但是也就這樣了。

直接存下來肯定是不現實的。全部都轉移也是不現實的。

怎麼辦?

觀察發現,有效的點實質上很少。

我們用得上的

x ,

y都是題目給出的。

我們把這些點叫為關鍵點。

你是不是已經知道怎麼做了呢?

我們只存下關鍵點的相關狀態。

什麼叫相關狀態呢?比如我這顆樹把

x 標記為關鍵點,為了更新

x,我們必須在之前的樹里都一直維護

x 的資訊,遞迴下去,把標記都打上,這就是這個關鍵點的相關狀態。

我們有n

棵樹,每棵樹最多標記2∗

n 個點,總共只有n∗

n∗2 個關鍵點 di

s[t]

[i][

j]的轉移是o(

n2) ,d[

t][i

] 轉移是o(

n)每棵樹都要更新狀態,總的時間複雜度是o(

n3)

這題非常靈活地運用了記憶化搜尋的遞迴性質。

其實這和一些常見的最短路只存關鍵點狀態是相似的。

只存關鍵點。

由於有點難理解所以我貼下**。

#include

#include

#include

using namespace std

;typedef pairpi;

typedef long long ll;

const int n = 130 , mo = 1e9 + 7

;pi bz[n][n];

struct nodeq[n];

ll size[n],dis[n][n][n],d[n][n];

int n,fi[n];

int mark(int x , ll p)

void solve()

for (int i = 2

; i <= n ; i ++)

int b , b1;

b = (!p.first) ? q[i].a : q[i].b

; b1 = (!p1.first) ? q[i].a : q[i].b

; dis[i][j][k] = ((dis[q[i].s[p.first]][b][p.second] + dis[q[i].s[p1.first]][b1][p1.second]) % mo + len ) % mo;}}

lch = q[i].a , rch = q[i].b

; for (int j = 1

; j <= fi[i] ; j ++)

lch = q[i].s[0], rch = q[i].s[1];

q[i].sum = d[lch][q[i].a] * size[rch] % mo;

(q[i].sum += d[rch][q[i].b]* size[lch] % mo) %= mo;

q[i].sum = q[i].sum + size[lch] * size[rch] % mo * len % mo;

q[i].sum = (q[i].sum + q[lch].sum) % mo + q[rch].sum % mo;

q[i].sum %= mo;

printf("%i64d\n" , q[i].sum);

}}int main()

清華冬令營2018模擬 送你一棵聖誕樹

對於每個詢問輸出一行乙個整數,表示答案.5 5 0 5 5 2 5 5 5 1 2 5 4 2 3 5 1 2 2 3 2 5 1 1 1 1 5 2 3 2 1 3 1 5 0 3 15 5 1 4 1 1 5 4 5 1 3 5 2 3 4 3 2 5 4 2 2 2 1 3 1 5 2 1 2...

送你一朵聖誕樹

貪心解決。這種考慮前後順序的題目的常見做法是前後比較將優先順序排序,再用並查集輔助合併。善用stl 如果要維護乙個堆的話,可以用set,最方便,stl的heap太麻煩,優先佇列可能被卡。注意,set中如果自定義了比較函式 還是比較複雜的那種,如本題的貪心 那麼set.find 很有可能re 不是找不...

教你用Python畫了一棵聖誕樹

如何用python畫乙個聖誕樹呢?最簡單 height 5 stars 1for i in range height print height i stars stars 2 print height 效果 哈哈哈哈,總有一種騙了大家的感覺。其實本文是想介紹turtle庫來畫聖誕樹。import t...