HEOI 2018 林克卡特樹

2022-03-27 02:05:49 字數 1749 閱讀 8893

先說60分的.

思路題解上很清晰:

問題似乎等價於選k+1條點不相交的鏈哎!

f(x,k,0/1/2)表示考慮以x為根的子樹,選了k條鏈,點x的度數為0/1/2的最優解.

我說一下比較坑的地方吧:

1.初始化要-inf(反正我不加這個會wa)

2.注意轉移的順序

3.別忘了突然出現新的路徑或者突然消失了乙個路徑的時侯加減1

4.一定要割k下

細節說多不多,說少不少,還得自己打.

說一下100分的.

60分的瓶頸在於k,那麼如果對於k沒有限制的話,那麼我們的轉移就會變成o(n)的(和60分的dp是差不多的).

如何去掉k的限制呢,我們考慮,我們的答案陣列關於下標是凸包(想一下就會發現很顯然啊).那麼我們想到凸包就會想卡他,那麼也就是我們設斜率去卡到k,那麼我們有了斜率會發生什麼呢.

我們的問題轉化為了——設斜率為cost,那麼就是求,這棵樹選取若干條不相交路徑,得到的貢獻是路徑邊權和,代價是每條路徑花費cost,求最終答案(最大化收益),及其路徑條數.

這樣我們每次二分出斜率之後會o(n)出解,得到路徑條數,從而繼續二分.

不難打,有了60分的dp之後,給到二分斜率的思路就應該可以寫出來了.

(補充一下:這玩意似乎是wqs二分……)

#include #include 

#include

char xb[(1

<<15)+10],*xs,*xt;

#define gtc() (xs==xt&&(xt=(xs=xb)+fread(xb,1,1<<15,stdin),xs==xt)?0:*xs++)inline

void read(int &x)

typedef

long

long

ll;const

int n=300010

;const ll inf=1e15;

struct

vc[n

<<1

];int

head[n],t;

inline

void add(int x,int y,int

z)int

n;ll k;

struct

a inline

void

set()

inline a up()

inline

void

cover(a a)

inline

void

cover(a a,a b)

inline

void cover(a a,a b,ll w,int

opt)

}f[n][3];

inline

void dfs(int x,int

fa) f[x][

1].cover(f[x][0

].up());

f[x][

2].cover(f[x][1

]); f[x][

2].cover(f[x][0

]);}

inline a solve()

intmain()

ll l=-1e12,r=1e12,mid,ans=0

; a ret;

while(l<=r)

printf(

"%lld\n

",ans);

return0;

}

kod

HEOI 2018 Day2 T2 林克卡特樹

給乙個n個節點的樹,然後將其分成k 1個聯通塊,再在每個聯通塊取一條路徑,將其連線起來,求連線起來的路徑最大權值。考場只會20分,還都打掛了 60分的做法其實並不難,nk dp即可,設 f i,j,0 1 2 表示i子樹選取了j個聯通塊,i這個節點連了0 1 2條邊時的最優解。100分的做法就是60...

2018八省聯考 林克卡特樹

題目真滴皮 orz rqy 10分的暴力都沒拿到 10分直接求直徑 60分 容易?想到題目等價於求k 1條不相交的鏈 設狀態f i j 0 1 2 f i j 0 1 2 表示以第i個節點為根的子樹用了j條鏈並且根和兒子連有 0,1,2 條邊。轉移分為5類 g j cc 0 max g j cc 0...

八省聯考2018 林克卡特樹

挺簡單的一道題。原題斷k kk條邊連k kk條邊權為0 00的邊相當於尋去k 1 k 1k 1條不相交鏈出來,將它們連上得到的結果。所以我們要從原樹中選取k 1 k 1k 1條鏈出來,使得它們的權值和最大。我們發現恰好k 1 k 1k 1條鏈這個限制是比較難限制的,考慮通過凸優化二分去進行維護。由於...