我怎麼越來越菜了。
首先,對於乙個物品,我們將它拆成若干份:最後一天拆成兩份,乙份的個數為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...