九省聯考2018 林克卡特樹 DP wqs二分

2022-03-27 07:33:07 字數 1354 閱讀 8921

對於k=0和k=1的點,可以直接求樹的直徑。

然後對於60分,有乙個重要的轉化:就是求在樹中找出k+1條點不相交的鏈後的最大連續邊權和。

這個dp就好。$o(nk^2)$

然後我們完全不可以想到,將best[k](選擇k條鏈的答案)打表輸出,更不可能然後作差分,發現得到的陣列是遞減的。

這說明:best[k]是乙個上凸包。

於是我們可以二分乙個斜率去切這個凸包(類似導數),根據切點橫座標與k的大小旋轉直線(改變斜率)。

考慮給你乙個直線斜率k,怎麼找到它和凸包的切點。實際上就相當於將這個凸函式減去y=kx,再求凸包最高點。

感性理解一下,就是相當於在凸包下面畫一條直線,然後旋轉整個座標係使這條直線就是x軸,然後正確性就比較顯然了。

現在問題就是,如何找到最高點,這成了乙個最優性問題,dp方程裡可以去掉一維(已選鏈數不需要記錄了)。

這樣就可以通過了,複雜度$o(kn\log n)$。這又叫wqs二分。

1 #include2 #include3 #include4

#define rep(i,l,r) for (int i=l; i<=r; i++)

5 typedef long

long

ll;6

using

namespace

std;78

const

int n=300010;9

int n,k,u,v,w,cnt,to[n<<1],nxt[n<<1],val[n<<1

],h[n];

10ll mid,tot;

11void add(int u,int v,int w)

12struct

p15 p operator + (const p &b) const ;}

16 p operator + (int b) ;}

17 }dp[3

][n];

18 p upd(p a); }

1920

void dfs(int u,int

fa));

22for (int i=h[u],v; i; i=nxt[i])

23if ((v=to[i])!=fa)

29 dp[0][u]=max(dp[0][u],max(upd(dp[1][u]),dp[2

][u]));30}

3132

intmain()

42 memset(dp,0,sizeof(dp)); mid=l; dfs(1,0); printf("

%lld\n

",l*k+dp[0][1

].x);

43return0;

44 }

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條鏈這個限制是比較難限制的,考慮通過凸優化二分去進行維護。由於...

八省聯考 2018 林克卡特樹

題意 求乙個凸函式的最優解。思路 好吧在題意裡已經說出來了。對於被卡斜率的,只能 orz 了。其實據說還有 12s 評測這種操作,對不起我省 5s 好吧不廢話了,看看應該怎麼做。暴力的話直接記 dp i j 0 2 表示當前做到第 i 棵子樹用了 j 條鏈並且當前點有 0 2 條出邊,轉移也好想。正...