BZOJ#3252. 攻略
生活随笔
收集整理的這篇文章主要介紹了
BZOJ#3252. 攻略
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
BZOJ#3252. 攻略
題目描述
Solution
有一個(gè)顯然的 貪心,每次選取一個(gè)到根的點(diǎn)權(quán)和最大的點(diǎn)xxx,將答案加上xxx到根的路徑的點(diǎn)權(quán)和,并將xxx到根的路徑上的點(diǎn)的權(quán)值清零。
可以使用DFS序+線段樹維護(hù)。
但完全沒有這么麻煩。
容易發(fā)現(xiàn)每一次選擇的到根的鏈,從兒子跳到父親的過程中,會(huì)從某一個(gè)時(shí)刻開始一直貢獻(xiàn)為0,因?yàn)橹耙呀?jīng)有一個(gè)鏈把上面的權(quán)值都清空了。如果我們丟棄掉上面一段權(quán)值和為0的鏈,相當(dāng)于每一條邊會(huì)且僅會(huì)被包括在一條鏈上,我們只需要每次貪心地選取權(quán)值和最大的鏈即可。
這一過程不就是長(zhǎng)鏈剖分的過程嗎?
我們將點(diǎn)權(quán)和當(dāng)做長(zhǎng)鏈剖分的剖分條件,將樹剖分成若干個(gè)互不相交的鏈,將這些鏈排序,取最大的kkk條鏈即可。
時(shí)間復(fù)雜度O(n+排序)O(n+排序)O(n+排序)
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=998244353; const int MAXN=600005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } vector<ll> V,e[MAXN]; ll len[MAXN],a[MAXN],mx[MAXN],s[MAXN],ans=0; void dfs1(int x,int father) {for (auto v:e[x]){if (v==father) continue;dfs1(v,x);if (len[v]>len[x]) len[x]=len[v],mx[x]=v;}len[x]+=a[x]; } void dfs2(int x,int top,int father) {if (mx[x]) dfs2(mx[x],top,x);for (auto v:e[x]){if (v==father||v==mx[x]) continue;dfs2(v,v,x);}if (top==x) V.PB(len[x]); } int main() {int n=read(),k=read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<n;i++) {int u=read(),v=read();e[u].PB(v);e[v].PB(u);}dfs1(1,0);dfs2(1,1,0);sort(V.begin(),V.end()); // for (auto v:V) printf("%lld\n",v);for (int i=1;i<=min(k,(int)V.size());i++) ans+=V[V.size()-i];printf("%lld\n",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的BZOJ#3252. 攻略的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [ZJOI2016]小星星
- 下一篇: P3899 [湖南集训]谈笑风生