HEOI 2018 Day2 T2 林克卡特樹

2022-03-01 15:22:25 字數 2380 閱讀 2159

給乙個n個節點的樹,然後將其分成k+1個聯通塊,再在每個聯通塊取一條路徑,將其連線起來,求連線起來的路徑最大權值。

考場只會20分,還都打掛了……

60分的做法其實並不難,nk dp即可,設$f(i,j,0/1/2)$表示i子樹選取了j個聯通塊,i這個節點連了0/1/2條邊時的最優解。

100分的做法就是60分做法的拓展。

很容易想到一件事,就是以聯通塊數為x軸,最優解為y軸,那麼這個影象應該是乙個單峰上凸函式。同時該離散函式每相鄰兩點間的斜率是遞減的:因為考慮當前聯通塊數為a,則當聯通塊數為a+1時,必然是在a時最優解上再連線一段新切出的可空路徑並割去一部分可空路徑,當補上一條新路徑時,我們很容易知道這次補上的路徑-割去路徑一定小於以前做的同樣操作(最優性)。

這樣我們發現斜率是具有單調性的(即單調減)。那麼我們二分這個斜率,並將原影象減去這個斜率對應的正比例函式,會發現,新影象將會在這個斜率對應點的位置最高,同時也是乙個斜率遞減函式。

那麼我們考慮如何求出此時的答案:新影象上的最高點權值+新影象上最高點聯通塊數*斜率。

我們考慮這個東西怎麼求。

設二元組$f(i,0/1/2)$表示i節點連了0/1/2條邊時的最優解和其聯通塊數(盡量小)。特別的沒有連邊的i,算為乙個聯通塊,2為0/1/2這三個狀態的最優解。

考慮這個東西怎麼轉移:

假設已經得到子節點v的答案。

對於$f(x,2)$,我們有三種選擇,1.保持原來不變,把$f(v,2)$加上;2.由$f(x,1)$和$f(v,1)$合併;3.由$f(x,1)和f(v,0)$合併。

$f(x,1)$,我們同樣有三種選擇,大體同上者。

$f(x,0)$,我們只有一種選擇,即和$f(v,2)$結合。

我們以$f(x,2)$為例:對於第一種情況,聯通塊數不變直接合併即可,對於第二種情況聯通塊數減少1,第三種情況同樣減少了1個聯通塊。

得到結果以後比較k+1與最優解對應的聯通塊數,大於則說明斜率過小,否則說明斜率還可能更大。

1 #include "

bits/stdc++.h"2

3using

namespace

std;

45 inline int

read()

1112 typedef long

long

ll;13

14const

int n=3e5+10;15

16struct

edgesedge[n<<1],*head[n];int

cnt;

1920 inline void push(int u,int v,int

w) ,head[u]=edge+cnt;22}

2324

intn,k;

25ll slope;

26const ll inf=1e15;

2728

struct

node

31node(ll v,ll nm):val(v),num(nm){}

32 inline ll &operator (int

x)35 inline void

max(node a)

39 inline void

add(node a,node b)

44 inline void add(node a,node b,int w,int

opt)

50inline node fa()

53 }f[n][3

];54

55 inline void dp(int x,int

fa)68 f[x][2].max(f[x][1

]);69 f[x][2].max(f[x][0

]);70 f[x][2].max(f[x][0

].fa());71}

7273

74int

main()

80 ll l=-1e12,r=1e12;

81node now;

82 ll ans=0;83

while (l<=r)

91 printf("

%lld\n

",ans);

92 }

NOIP2018 Day2 T1 旅行 題解

乍一看,一道基環樹。說實話考場上有點懵,day2t1直接上基環樹?再一看,好像只是一道無腦的搜尋加剪枝 對於noip資料範圍,o n 2 是可以可過去的 但是對於那個加強版資料,可能需要乙個筆者不會的超級玄學。好吧不扯了,咱們來看看資料範圍。m n 1的情況比較簡單只需一遍跑一邊搜尋,每次找字典序最...

CTSC2018 Day2T1 Juice混合果汁

題解 在考場上a掉的題。把美味度排個序,然後按照 p為權值建立主席樹,把每個果汁按照拍好的順序新增進去。主席樹上維護總公升數cnt以及總 sum。對於每個詢問,我們二分乙個美味值,check的時候去主席樹上查詢大於等於這個美味值的果汁中購買l公升的 即可。1 include2 include3 de...

嵊州普及Day2T2

題意 對於n個數的數列,進行排列,求第m個大於此數列的數列。思路 查詢後2個是否逆序,若是,將後3個遞迴。如此運算,找後面大於此數中最小數交換,然後將後面數列順序排列。相對簡單。見 include include include include include using namespace std...