Luogu P4103大工程(虛樹DP)

2022-05-01 00:45:14 字數 2640 閱讀 6632

題目鏈結

我貌似發現這類dp就是先別管什麼虛樹……把樹形dp搞出來套上虛樹板子就好了

這個樹形dp就是設sum為答案,sumd為子樹內所有點的深度和(當然指的是被詢問的點),maxi指子樹內最深的點的深度,mini同理

然後考慮我們dfs到x,它的兒子已經遍歷到一半,新加進來乙個兒子to

顯然$sum[x]+=sum[to]+(sumd[x]-deep[x]*size[x])*size[to]+sumd[to]-deep[x]*size[to]$

$sumd+=sum[to]$

$maxi[x]=max(maxi[x],maxi[to])$

只要注意這類方程的先後順序即可。

另外注意輸出的先後順序。

#include#include

#include

#include

#include

#define maxn 1020020

using

namespace

std;

inline

long

long

read()

while

(isdigit(ch))

return num*f;

}long

long

sum[maxn],maxi[maxn],mini[maxn];

long

long

sumd[maxn];

long

long

ansa[maxn],ansb[maxn];

long

long

size[maxn];

long

long

dfn[maxn];

long

long

deep[maxn];

long

long

q[maxn];

long

long

stack[maxn],top;

long

long s[maxn][22

];bool

vis[maxn];

long

long

id;struct

picedge[maxn*2

];

long

long

head[maxn],num;

inline

void add(long

long

from,long

long

to);

head[

from]=num;

}void pre(long

long x,long

long

fa)

return

; }

void dele(int x,int

fa) head[x]=0

; }

void dfs(long

long x,long

long

fa)

if(vis[x])

//printf("%lld %d\n",sum[x],x);

return

; }

}old,vir;

bool cmp(long

long a,long

long b)

inline

long

long lca(long

long x,long

long

y)

return s[x][0];}

intmain()

old.pre(

1,1);

for(long

long j=1;j<22;++j)

for(long

long i=1;i<=n;++i) s[i][j]=s[s[i][j-1]][j-1

];

long

long m=read();

while(m--)

//printf("\n");

sort(q+1,q+e+1

,cmp);

for(long

long i=1;i<=e;++i)

long

long lca=lca(q[i],stack[top]);

while(dfn[lca]vir.add(stack[top-1

],stack[top]);

top--;

}stack[++top]=q[i];

}while(top>1

) vir.dfs(stack[

1],stack[1

]); printf(

"%lld %lld %lld\n

",sum[stack[1]],ansb[stack[1]],ansa[stack[1

]]);

for(long

long i=1;i<=e;++i) vis[q[i]]=0

; vir.dele(stack[

1],stack[1

]); }

return0;

}

P4103 HEOI2014 大工程 虛樹

虛樹板題一道。個人覺得這題比 消耗戰 更適合練板子 樹形dp更為簡單 說正解。注意到 p 2e 6 sum p le2e6 p 2 e6,這提示我們建一顆虛樹。建好後,2和3問就是求乙個樹上最短路,最長路,不再贅述。簡單說一下1,我們對於每一條邊統計有多少點對經過它。具體的,樹形dp的時候算出,即為...

P4103 HEOI2014 大工程 (虛樹)

觀察資料範圍是跟k有關的,因此我們考慮建立虛樹,對於維護三個值 總和就是常規的按每條路左右兩邊點數算貢獻,注意是特殊點的數量 之後我們維護mi i mx i 表示對於當前點,子樹中離他最近的特殊點在哪 includeusing namespace std typedef long long ll t...

P4103 HEOI2014 大工程 虛樹

戳這裡 虛樹板子題 首先有乙個 o qn 的暴力,就是對於每一次詢問,o n 的樹上 dp 我們統計一下每乙個點,它的子樹內離它最近 遠的關鍵點的距離,已經關鍵點的個數 對於第乙個詢問等價於 sum dep x dep y sum2 times dep lca 我們 dp 的時候順便統計一下每乙個點...