loj 6184 無心行挽 虛樹 DP 倍增

2021-09-10 02:37:26 字數 3478 閱讀 4435

首先,這題肯定要用虛樹。

接下來,你會發現,使得f(u

)f(u)

f(u)

最大的u

uu,可能存在於三個位置:

虛樹上虛樹上乙個沒有關鍵點的子樹中

虛樹上的一條邊中

於是便分類討論。

對於第一種情況,只需要在虛樹上做dp求出虛樹上的每個點x

xx到最近的關鍵點的距離dtk

p(x)

dtkp(x)

dtkp(x

)即可(dist to key point)

對於第二種情況,我們對整棵樹dp,得到每個點到子樹中的點的最遠距離fir

(x

)fir(x)

fir(x)

,然後將它的兒子們按照fir從大到小排序。對於虛樹上的每個點x

xx,找到第乙個不在虛樹上的兒子y

yy,用fir

(y)+

1+dt

kp(x

)fir(y)+1+dtkp(x)

fir(y)

+1+d

tkp(

x)更新答案。

對於第三種情況,比較麻煩。我們對整棵樹dp的時候,還要得到乙個se(

x)

se(x)

se(x

),表示x

xx不走能夠造成fir

(x

)fir(x)

fir(x)

貢獻的那棵子樹,離最遠點的距離。於是我們就可以預處理兩個倍增陣列:u(j

,i

)u(j,i)

u(j,i)

和d (j

,i

)d(j,i)

d(j,i)

在j =0

j=0j=

0時的值。

u (j

,i

)u(j,i)

u(j,i)

:i

ii走到原樹上的前2

j2^j

2j個祖先中的乙個後,再往該祖先的一棵子樹裡走,用這樣的策略可以走的最遠距離。

d (j

,i

)d(j,i)

d(j,i)

:i

ii的原樹上前2

j2^j

2j個祖先中的乙個,往自己的子樹裡走,不經過子樹i

ii可以走的最遠距離。

不難發現,如果我們規定虛樹上的乙個點x

xx和它兒子y

yy中間邊上的點,全部必須先走到x

xx再走到關鍵點,貢獻可以通過d

dd算出來。而若全部必須先走到y

yy再走到關鍵點,貢獻可以通過u

uu算出來。

通過d tk

p(x)

dtkp(x)

dtkp(x

)和dtkp

(y

)dtkp(y)

dtkp(y

)的值,我們就可以確定這條邊從哪個位置開始劃分,上面的點全走到x

xx再去關鍵點,下面的點全走到y

yy再去關鍵點,就能算出答案了。

複雜度o(n

log⁡n)

o(n \log n)

o(nlogn)

#include

using

namespace std;

#define ri register int

intread()

const

int n=

100005

,inf=

0x3f3f3f3f

;int n,q,tot,ans,qcnt,tim,top,rub_top;

int h[n]

,ne[n<<1]

,to[n<<1]

,pos[n]

,fir[n]

,se[n]

;int f[17]

[n],u[17]

[n],d[17]

[n],dep[n]

,bin[17]

;int q[n]

,is[n]

,st[n]

,dtkp[n]

,rub[n]

,cantgo[n]

;vector<

int> son[n]

;void

add(

int x,

int y)

bool

cmpson

(int x,

int y)

void

dfs(

int x,

int las)

sort

(son[x]

.begin()

,son[x]

.end()

,cmpson)

;for

(ri i=h[x]

;i;i=ne[i])}

void

prework()

}int

lca(

int x,

int y)

intgoup

(int x,

int d)

intgetd

(int x,

int d)

intgetu

(int x,

int d)

bool

cmp(

int x,

int y)

void

dp1(

int x)

}void

dp2(

int x)

}void

getans

(int x)

}getans

(to[i]);

}int sz=son[x]

.size()

;//無關鍵點的子樹中

for(ri i=

0;i++i)if(

!cantgo[son[x]

[i]]

) h[x]=0

;}void

work()

else

break;}

if(st[top]

!=o) st[

++top]

=o; st[

++top]

=x;}

while

(top>1)

add(st[top-1]

,st[top]),

--top;

dp1(1)

,dp2(1

),getans(1

);for(ri i=

1;i<=qcnt;

++i) is[q[i]]=

0;for(ri i=

1;i<=rub_top;

++i) cantgo[rub[i]]=

0;}int

main()

return0;

}

loj2850 無進製加法

似乎漏了乙個資料範圍,cf上的題面中還有 sum l le 3 cdot 10 考慮 a 2 時 不妨 k ge k ge ge k 記 sum b 的最高位為 l 則有 l max k i 1 證明 大於等於 2 的 b 至少要 i 個,因此該值即為下限 取 b 2 i 1 ge 2 因此一定可行...

無源匯可行流 模板LOJ 115

自個設個源點s,匯點t,每個點 du i 入度 出度。du i 0時 加邊s i,邊權為du i du i 0時 加邊i t,邊權為 du i 設sum為所有 0的du i 的和 求s t的最大流,如果maxflow sum,則存在可行流,此時每條邊流掉的流量 它原本的下界就是實際的流量 dfs過程...

無源匯有上下界可行流 loj模板

loj模板題 思想是 如果存 在可行流 每條邊 必定至少 有下界的 流量 思想是,如果存在可行流,每條邊必定至少有下界的流量 思想是,如果 存在可行 流,每條 邊必定至 少有下界 的流量 那 麼直 接用下屆 填充邊的 流量 那麼直接用下屆填充邊的流量 那麼直接用下 屆填充邊 的流量 每 條邊 的流量...