戳這裡
虛樹板子題
首先有乙個 \(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...