P4103 HEOI2014 大工程 虛樹

2022-06-13 20:54:09 字數 1307 閱讀 4911

戳這裡

虛樹板子題

首先有乙個 \(o(qn)\) 的暴力,就是對於每一次詢問, \(o(n)\) 的樹上 dp ,我們統計一下每乙個點,它的子樹內離它最近/遠的關鍵點的距離,已經關鍵點的個數

對於第乙個詢問等價於 \(\sum dep(x)+dep(y)-\sum2\times dep(lca)\)

我們 \(dp\) 的時候順便統計一下每乙個點作為 \(lca\) 出現了多少次,這個直接掃一下兒子就能得到

第二個詢問按照我們 \(dp\) 陣列記下的狀態列舉一下兩個子樹就可以得到

我們發現這種樹上\(dp\)多次詢問每次給定點集(點集總和與 \(n\) 同階)的問題直接建出虛樹這樣每次 \(dp\) 的複雜度降低到和點數同階,總的複雜度不超過 \(o(n\log)\)

#includeusing namespace std;

namespace zzc

while(isdigit(ch))

return x*f;

}const int maxn = 1e6+5;

const int inf = 0x3f3f3f3f;

int n,idx,num,top,qt,ans2,ans3,mx[maxn],mn[maxn];

long long ans1;

int dfn[maxn],fa[maxn][22],st[maxn],p[maxn],dep[maxn],sum[maxn];

bool vis[maxn];

struct tree

e[maxn<<1];

void add(int u,int v)

}t1,t2;

bool cmp(int x,int y)

}return fa[x][0];

}inline void build()

else t2.add(x,st[top--]);

}st[++top]=p[i];t2.head[p[i]]=0;}}

while(top>1) t2.add(st[top-1],st[top]),top--;

}void dfs2(int u,int ff)

} }inline void solve()

void work()

dep[0]=-1;dfs1(1,0);

for(int j=1;j<=21;j++)

}qt=read();

while(qt--)

}}int main()

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...

HEOI2014 大工程 虛樹 樹形DP

還不錯,就是理解題意的時候理解的久了一些。題目中的距離實際上是每兩個點在原樹上的距離,而新建的結點是不會影響的,所以總的距離和是原樹上任意兩點的距離之和 最短距離呢,實際上就是最短邊權了 最長距離,實際上就是新構成虛樹上樹的直徑了,當然得是有效點的。所以,構建虛樹,然後再進行乙個樹形dp就可以了。i...