2018八省聯考 林克卡特樹

2021-08-18 16:34:42 字數 2750 閱讀 3753

題目真滴皮

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],f[x][j][0]+max(f[v][cc][0],max(f[v][cc][1],f[v][cc][2])));

if(cc) g[j+cc][1]=max(g[j+cc][1],f[x][j][0]+f[v][cc][1]+tb[i].w);

if(j) g[j+cc][1]=max(g[j+cc][1],f[x][j][1]+max(f[v][cc][0],max(f[v][cc][1],f[v][cc][2])));

if(j) g[j+cc][2]=max(g[j+cc][2],f[x][j][2]+max(f[v][cc][0],max(f[v][cc][1],f[v][cc][2])));

if(j && cc) g[j+cc-1][2]=max(g[j+cc-1][2],f[x][j][1]+f[v][cc][1]+tb[i].w);

100分正解 好像是叫wqs二分的東東。

如果不考慮k的話可以省掉一維讓時間複雜度達到o(

n)o (n

)用f[

i][0

/1/2

] f[i

][0/

1/2]

表示以i為根的子樹 balabala

經過一番推導打表驗證 f是乙個凸函式

他的差分陣列單調遞減。 可以dp求得最大值和鏈的個數和k比較一下。

顯然如果對於差分陣列整體減乙個數的話最大值點是會左移的那麼就可以二分這個減去的數啦。

設減去的數為 s

怎麼減去整個數呢? 設g

[i] g[i

]表示i條鏈的答案 那麼設h[

i]=g

[i]−

i∗s h[i

]=g[

i]−i

∗s

hh

的差分陣列就可以讓每乙個減去s了

上下界l,r。 r=所有正權值和,l=最大正權邊的相反數。

分別對應著差分陣列的兩極。

//林可卡特樹  wqs二分 

#include

#include

#include

#include

#include

#include

#include

#pragma comment(linker, "/stack:1024000000,1024000000")

using namespace std;

const int maxn=300000+10;

const int maxn1=100000+5;

typedef long long ll;

int n,k;

struct node

tb[maxn*2];

int len,h[maxn];

ll f[maxn][5],g[maxn][5],qq[5],q[5];

ll ans,sum,sz[maxn],s,l,r;

bool flag[maxn];

void add1(int i,int j,int w)

; h[i]=len;

}void max(ll &val,ll &num,ll newval,ll newnum)

}void dfs(int

x,int fa)

ll max1=f[v][0],maxnum=g[v][0];

max(max1,maxnum,f[v][1],g[v][1]); max(max1,maxnum,f[v][2],g[v][2]);

max(f[x][0],g[x][0],qq[0]+max1,maxnum+q[0]);

max(f[x][1],g[x][1],qq[1]+max1,maxnum+q[1]);

max(f[x][1],g[x][1],qq[0]+f[v][1]+tb[i].w,q[0]+g[v][1]);

max(f[x][2],g[x][2],qq[2]+max1,maxnum+q[2]);

max(f[x][2],g[x][2],qq[1]+f[v][1]+tb[i].w+s,q[1]+g[v][1]-1);

}}int main()

k++;

while(ls=(l+r)>>1;

dfs(1,0);

ll max1=f[1][0],maxnum=g[1][0];

max(max1,maxnum,f[1][1],g[1][1]); max(max1,maxnum,f[1][2],g[1][2]);

if(maxnum>k)

l=s+1;

else

r=s;

}s=l;

dfs(1,0);

ll max1=f[1][0],maxnum=g[1][0];

max(max1,maxnum,f[1][1],g[1][1]); max(max1,maxnum,f[1][2],g[1][2]);

cout<*s

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 條出邊,轉移也好想。正...

八省聯考2018 林克卡特樹

題目描述 小l 最近沉迷於塞爾達傳說 荒野之息 the legend of zelda breath of the wild 無法自拔,他尤其喜歡遊戲中的迷你挑戰。遊戲中有乙個叫做 lct 的挑戰,它的規則是這樣子的 現在有乙個n 個點的 樹 tree 每條邊有乙個整數邊權vi 若vi 0,表示走這...