ACM 11月26日週日週末訓練心得

2021-08-11 08:11:46 字數 1597 閱讀 5933

這週末關於樹形dp的專題已經結束了,需要對這個專題進行一下總結,就我做的這些題進行一下總結。

樹形dp就是根據問題的描述,問題裡的東西與樹一樣擁有子節點和父節點的關係,而做一些對於這些資訊的檢索以及尋找一些問題所需要的答案則需要尋找一些狀態變化和轉移。選擇一些對樹形dp印象比較深刻的題目進行思考。

a這道題大致的意思是,乙個公司裡的職員關係就像一顆樹一樣存在上下級關係,乙個員工可能是另乙個員工的上級,要求盡可能選更多的員工,並且他們都沒有上下級的關係,使得快樂值最大。這道題首先就要確定對於乙個員工i來說,選擇這個員工或者不選這個,所以可以有dp[i][0]為不選擇i的時候最大的快樂值,dp[i][1]為選擇i的時候的最大值,所以接下來的狀態就是圍繞i的子節點的情況進行討論,不選擇i的時候,i的下屬可以選擇,也可以不選擇,主要還是尋找快樂值最大的方法,故有dp[i][0] += max(dp[i的下屬][0], dp[i的下屬][1]);選擇i的時候那麼所有i的下屬都不能選,所以有dp[i][1]+=dp[i][0]。

b這道題的意思是先給你每個電腦的連線關係,求的是每台電腦與最遠的乙個電腦的距離是多長,對於這個問題,每個電腦都可以簡化為樹上的乙個節點,對於每乙個電腦他的轉移方向都有兩個,乙個是向他的子節點移動,乙個是向他的父節點移動,這兩個方向中找到最遠的節點,故有dp[i][0]記錄電腦i子節點的最長距離,belong[i][0]記錄子節點最長路徑經過的i的子節點。dp[i][0]記錄電腦i子節點的第二長距離,down[i][0]記錄向下第二長路徑經過的i的子節點需要設定旗幟flag[i] = 0代表i的父節點的最長路徑不經過i,flag[i]=1代表i的父節點的最長路徑經過i。狀態轉移方程就是找出所有點向下的距離,然後由父向子的順序進行遍歷,設i是j的父節點如果節點j的flag[j] = 0 ,那麼它的最遠距離應該是dp[j][0] 和 i的最遠距離+i到j的距離 中的最大值。如果節點j的flag[j] = 1 ,那麼它的最遠距離應該是 dp[j][0]和i的不包含j的路徑的距離+i到j的距離中的最大值。這道題的不同就是用了dfs的思想並且題目有乙個樹形。 

t這道題有一些非主流,這道題的樹跟之前的有很大的不一樣,題意大致是給出乙個樹的每個節點的值,然後進行一次裁邊使這顆數變成兩部分,求這兩部分權值之差最小,這道題我一開始沒有選擇用樹形dp,就是瘋狂列舉,然後感覺會tle,重新思考這道題用樹形dp的方法,感覺這個方法還不夠樹形dp,看了一些別人的部落格,用dp[u]來表示在u的權值之和,然後用dfs進行遍歷。

void dfs(int x,int f)

{ dp[x]=a[x];

for(int i=0;i題o印象也比較深刻,大概的意思是給定乙個存在n個節點的樹,從1到n去每條路耗費一定的時間,每經過乙個點就可以獲得這一點的權值,問如何在t時間內能到達n點並且獲得的權值盡量多 。這道題的思考路程差不多是先找到最短路徑的權值和最短路徑上的每個點,然後由於經過每個點都需要時間,要找到時間收益最大以i為起點給他j的時間能獲得的最大權值dp[i][j]。然後再算如何在最短路徑上的節點分配使得最終的權值最大。dp[i][j]的意思就是從i出發並回來花費j時間所得的最大權值。狀態轉移方程就是dp[i][j]=dp[i的子節點1][該點分配的時間] + dp[i的子節點2][該點分配的時間] + ... + dp[i的子節點n][該點分配的時間]。

樹形dp這個專題主要還是將dfs的問題與樹形的結構相結合。

ACM 11月19日週日週末訓練心得

這週看了樹形dp的一些部落格,比如一道compuer的題目要去求樹上每個點的最遠距離是多少,這題一直被稱為樹形dp的經典是有它的道理的,因為樹dp就是把dp放到樹上做了,一般是從上到下或從下到上 利用回溯 的移轉狀態而這題很合適的需要兩次dfs。對於 有向 dp u 0 表示在u的子樹下u的最遠距離...

ACM 9月3日週日週末訓練心得

今天老師發了新的專題,是線段樹的,今天就用空餘的時間看了看前輩的部落格,了解了一下線段樹的內容,發現樹狀陣列能解決的問題線段樹基本都能解決,線段樹的用法與樹狀陣列的用法似乎有些相似,但是線段樹能維護一段區間的值,不像樹狀陣列,改變乙個地方的值就會整體更新,線段樹有時候就比樹狀陣列好用了 線段樹需要維...

ACM 10月1日週日週末訓練心得

由於我們讀入該掃瞄線後sum 1 的覆蓋值少了5,但是此時我們看圖知道其實這個矩形的另一條上邊了.所以我們不能用ans sum 1 了,我要執行ans abs last sum 1 其中last是上一輪讀入掃瞄線後sum 1 的值。void pushup int i,int l,int r else...