UOJ 318 NOI2017 蔬菜 貪心

2022-03-31 14:43:49 字數 1312 閱讀 6025

我怎麼越來越菜了。

首先,對於乙個物品,我們將它拆成若干份:最後一天拆成兩份,乙份的個數為1 ,價值為 a+s;另乙份的個數為 (c-1) mod x,價值為 a。對於在 $(c-1) / x $ 天以及以前,每天有乙份個數為 x,價值為 a 的物品。

於是,用堆維護物品,每次取最大價值的,就可以在 \(o(n ^ 2 m \log n)\) 的時間複雜度內得到乙個詢問的答案。

考慮將所有物品分成兩種:

這種物品個數為 x,價值為 v 。

這種物品個數為 x,價值為 v,而且每天又會憑空多出 x 個。

然後同樣用堆維護,可以做到 \(o(n m\log n)\) 回答單次詢問。

如果我們得到了 \(k\) 天的答案,那麼我們只需要扔掉價值最小的一些物品,使得剩餘物品數 \(\leq (k-1) m\) ,就可以得到 \(k-1\) 天的答案。

於是我們只需要算出 100000 天的答案,然後倒推,即可預處理出所有詢問的答案。

總時間複雜度 \(o(nm\log n+ k)\)。

#include #define clr(x) memset(x,0,sizeof x)

#define for(i,a,b) for (int i=(a);i<=(b);i++)

#define fod(i,b,a) for (int i=(b);i>=(a);i--)

#define fi first

#define se second

#define pb(x) push_back(x)

#define mp(x,y) make_pair(x,y)

#define outval(x) cerr<<#x" = "priority_queue ,greater > q;

priority_queue q;

vector tmp;

ll res[n];

int main()

else

} ll ans=0;

fod(i,lim,1)

tmp.clear();

for(cc,1,m)

ans+=now.v;

q.push(now.v);

now.x--;

q.push(now);

} while (!tmp.empty())

q.push(tmp.back()),tmp.pop_back();

} fod(i,lim,1)

} while (k--)

printf("%lld\n",res[read()]);

return 0;

}

bzoj3936 Noi2017 蔬菜 貪心

題目描述 題解 這道題可以從後往前貪心。若我們知道了第i的答案,我們只要去掉 當前個數 前i 1天能取的個數 個價值最小的蔬菜,就能得到第i 1天的答案。所以我們現在只要求出最後一天的答案。把每種蔬菜拆成兩份,前c 1個價值為a,最後乙個價值為a s 按變質的順序 放入優先佇列中,依次取出來放入還能...

NOI2017 蔬菜 時光倒流 貪心

題目鏈結 題解 貌似一眼看過去是乙個貪心。其他的演算法要記錄的東西就太多了。部分分其實很高。但是沒有什麼提示。想一些套路 二分?不行還要貪心判斷。分治?前後取法是有影響的。時光倒流?也許可以?其實比較麻煩的是蔬菜變質。這樣就使得我們不能每次賣最貴的。如果時光倒流,那麼就會有些蔬菜在某乙個時刻以某乙個...

刷題 BZOJ 4946 Noi2017 蔬菜

網上大部分都是並查集寫法,但是有大神寫了非並查集寫法,特別容易理解 首先 s i 的限制,只需將每乙個蔬菜分出乙個價值為 a i s i 且過期時間為該蔬菜最晚的一天的蔬菜 把時間倒序之後,問題轉化為每個蔬菜會在第幾天出現,每天貪心選擇價值最大的即可 先求出 max 的答案,然後遞推 1,max 1...