題目鏈結
好像之前模擬賽考過原題,不過這個題的題意是真的看不懂,還有題解區都說省選出原題,原來省選都會出原題的呀,我吐了。
給陣列 \(a\)(\(0 <= a_i <= n\)) 和 \(w\),它的乙個排列合法當且僅當對於 \(p[j] <= p[k]\),那麼不存在 \(a_ == p[k]\),定義該排列的價值為 \(\sum_^i*w_\),要求是價值最大化。
反正在沒有看題解之前我連題意都讀不懂,u1s1,這道省選題出的是真的爛啊,不過題中的套路還是不錯的。
我們可以把題意轉化為對於 \(a[i] = k\),那麼在 \(p\) 陣列裡 \(k\) 要放到 \(i\) 的前面,我們考慮建圖,對於這樣的情況我們 \(k->i\),即 \(k\) 連向 \(i\)。
圖如果是一棵基環樹,那麼本題無解,否則是一棵以 \(0\) 為根的樹,題目轉化為給定一棵樹,每個節點都有乙個價值,要求選乙個節點必須先選它的父親,求最大價值。
我們不難想到經典的套路題,取出當前 \(w\) 最小的點,如果它已經沒有父親了,那麼直接計算答案,否則把它和它的父親合併成乙個點,且新點的權值定義為它們權值的平均數,然後重複該過程,得到的便是答案。
對於為啥是權值的平均值,這個是可以推柿子的,因為每次合併相當於兩個序列合併,隨便推一下柿子就可以得到平均值的結論了。
其實這道題的實現方法還是挺值得研究的,主要是利用堆來實現,並且用並查集來維護聯通塊和最新的情況,方便即時排除堆中過時的元素,利用0號節點方便直接計算答案。
// by longdie
#include #define ll long long
using namespace std;
const int n = 5e5 + 5;
ll ans, w[n];
int n, a[n], fa[n], siz[n];
struct node
node(int a, ll b, ll c)
friend bool operator < (const node &a, const node &b)
}; priority_queueq;
inline int find(int x)
inline void merge(int x, int y)
signed main()
for(register int i = 0; i <= n; ++i) fa[i] = i, siz[i] = 1;
for(register int i = 1; i <= n; ++i)
scanf("%lld", &w[i]), q.push(node(i, w[i], 1));
while(q.size())
cout << ans << '\n';
return 0;
}
題解 HNOI AHOI2018 毒瘤
題目傳送門 給出乙個 n 個點 m 條邊的無向圖,問有多少個點集滿足點集中任意兩點均不存在邊相連。n le 10 5,m n le 10 答案對 998244353 取模。妙啊!首先我們從樹的形態開始考慮,你發現答案其實就是獨立集的個數,具體來說我們可以設 f 表示 u 點選或不選的方案數,可以得到...
HNOI AHOI2018 尋寶遊戲
hnoi ahoi2018 尋寶遊戲 思維好題。將每一位領出來,組成 m 個長度為 n 的二進位制數。考慮將操作轉化為 01 序列,lor to0,land to1 觀察之後發現要使得第 j 位運算結果是 1 則最後乙個 lor1 操作的位置一定要在 land0 後面。轉化一下就是就要求 x gt ...
洛谷 HNOI AHOI2018 道路
初見安 這裡是傳送門 洛谷p4438 道路 題目乍一看很複雜,其實挺簡單的 就是一棵有根的滿二叉樹,要從每個葉子節點出發到根節點,每條路有個性質,公路or鐵路,現在要選n 1條道路翻新,滿足題目所述的條件。看n的範圍明顯是不能暴力列舉的。但是我們可以抓住一點 樹的深度不超過40。也就是說每個節點到根...