題解向 帶悔貪心泛做

2022-03-13 08:23:11 字數 2945 閱讀 1317

\(\rm fj\)準備買一些新奶牛,市場上有\(n\)頭奶牛\((1\leq n\leq 50000)\),第\(i\)頭奶牛**為\(p_i~(1\leq p_i\leq 10^9)\)。\(\rm fj\)有\(k\)張優惠券,使用優惠券購買第\(i\)頭奶牛時**會降為\(c_i~(1\leq c_i\leq p_i)\),每頭奶牛只能使用一次優惠券。\(\rm fj\)想知道花不超過\(m~(1\leq m\leq 10^)\)的錢最多可以買多少奶牛?

嗯,一般這種東西都是先假定乙個看起來有點合理的順序大力貪心,比如可以按照\(c_i\)排序去選小的。但這個貪心顯然不對,比如這個樣例:

k=1,n=2,m=12

p1=10,c1=1

p2=2^-1,c_2=2

那就顯然應該對第二個用,但貪心會去用掉第乙個。所以考慮怎麼反悔。觀察到選完\(\rm c_i\)之後,要麼選乙個最小的\(\rm p_j\),要麼換出來一張優惠券去選\(\rm c_j\)。於是考慮維護兩個堆,乙個維護沒用過coupon的\(\rm \\)的最小值,乙個維護用過了coupon的\(\rm \\)的最小值了。

struct cowsc[maxn] ; 

bool vis[maxn] ;

int n, k, ans ; ll m ;

struct comp1

};struct comp2

};struct co***

};priority_queue, comp1> q1 ;

priority_queue, comp2> q2 ;

priority_queue, co***> q3 ;

int main()

for (i = 1 ; i <= k ; ++ i)

for (i = k + 1 ; i <= n ; ++ i)

int p = q2.top().p, q = q2.top().c + q3.top().p - q3.top().c ;

if (p < q)

else

} cout << ans << endl ;

}

給定一長度為\(n\)個環,環上相鄰的兩個位置的權值(有正有負)只能選乙個,最多選\(k\)個位置,最大化選擇的權值和。

嗯,考慮比較弱智的貪心自然是從最大的開始選,然而這麼搞顯然不對。於是考慮怎麼去帶悔貪。觀察如果我們選了\(i~(i>1)\),那麼\(i-1\)和\(i+1\)就都不能選了;而如果想要悔這一次操作,那必定是希望選\(i-1\)或者\(i+1\)(否則不用悔)。

假設現在選了\(k\)個,要選第\(k+1\)個,那麼考慮把\(i\)扔掉之後實際上這一輪需要選兩個才能保證不會出現狀態轉移失秩的情況;同時,當且僅當\(val_+val_>val_i\)或者\(val_>val_i\)時,才會選\(i+1\)(不取等號是因為選了\(i-1\)和\(i+1\)如果和選\(i\)效果相同,那麼一定會去選\(i\)不會更劣,否則\(i-2,i+2\)也不能選),前者情況已經討論過,後者由於一開始的貪心就已經決定了\(val_\)會先選(即不會出現後者這種情況)。

於是就可以帶悔貪心,每次合併一下即可。

namespace greedy

cout << ans << endl ;

}}

by the way,本題有乙個比較顯然的\(dp\),設\(f_\)表示前\(i\)個元素選了\(j\)個的\(\max\),轉移的時候從\(f_\)和\(f_\)和\(f_\)轉移一下即可。

……發現隨手差分一下就是上一題的序列版本,於是就做完了。

。。。四倍經驗可還行啊

已知接下來\(n\)天的****,每天你可以買進一股**,賣出一股**,或者什麼也不做。

\(n\)天之後你擁有的**應為\(0\)。當然,希望這\(n\)天內能夠賺足夠多的錢.

考慮弱智貪心,大概就是掃一遍,遇到能買的就買,遇到價高的就賣出,最後減去多買的。但這東西顯然不對。於是考慮如何反悔,發現反悔的實質就是把原來賣出的那一天換成**。發現這樣原本的差價是\(y-x\),現在變成了\(z-x\),那麼反悔一次的獲的利就是\((z-x)-(y-x)=z-y\)。於是拿倆堆,乙個維護**的,乙個維護賣出的即可。

for (i = 1 ; i <= n ; ++ i) scanf("%d", &base[i]) ;

for (i = 1 ; i <= n ; ++ i)

q1.pop(), ans += p, q2.push((nd)) ;

} else

nd n = q2.top() ; q2.pop() ;

ans += q, q2.push((nd)), q1.push(base[n.id]) ;

}//// cout << ans << endl ;

} cout << ans << endl ; return 0 ;

有\(n\)個建築,修理工人修理完乙個建築才能修理下乙個建築,且不能同時修理多個建築。每個建築有乙個\(t_i\)修建該建築需要用的時間,\(e_i\)表示報廢的時間。如果某個建築在一段時間之內沒有完全修理完畢,這個建築就報廢了。制訂乙個修理順序,以搶修盡可能多的建築。

\(n\leq 2e5\)

由於沒有起始時間的限制,於是可以亂搞。考慮按照\(e\)排序,從前往後選,遇到乙個新的時,考慮怎麼反悔——反悔=之前的不修,那麼如果發現之前修的裡面有用時比現在這個大的,那肯定是修現在這個更合適,於是反悔一下即可。

bool comp(bds a, bds b)

int main()

else if (!q.empty())

} cout << ans << endl ; return 0 ;

}

codeforces1141D題解 暴力 貪心

給出兩個長度為 n 1 n 150000 的僅含有小寫字母和 的字串,詢問兩個字串最多能有幾對匹配的字元。每個字母都可以與和它相同的字元匹配,可以與任意字元匹配,匹配與位置無關 輸出最大匹配對數,以及每一對中兩個字元在字串中的位置 cf1141d created by hao on 2019 4 1...

題解向 正睿Round435

10.14 link 唔,這一場打得不好。獲得了 rm 75pts 300pts 的得分,但是居然可以獲得 rm 27 69 的名次,也不至於不滿意 畢竟是真不會233 大概就是字典序那個地方比較 於是就考慮奇數開頭和偶數開頭分開做,對於每種情況調整成乙個合法最小代價序列。這個地方有乙個貪心,原來在...

NOI2 6 9271奶牛散步 帶思路題解

這題相當的毒,要取餘12345卻不告訴你,太可惡了。題目傳送門 9271 奶牛散步 總時間限制 10000ms 單個測試點時間限制 1000ms 記憶體限制 131072kb 描述從乙個無限大的矩陣的中心點出發,一步只能向右走 向上走或向左走。恰好走n步且不經過已走的點 共有多少種走法?輸入乙個數字...