日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CF1380D.Berserk And Fireball 【2000】你值得学习的【思维】+【模拟】+【贪心】

發布時間:2023/12/16 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF1380D.Berserk And Fireball 【2000】你值得学习的【思维】+【模拟】+【贪心】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接

CF1380D.Berserk And Fireball

題意

  • 存在 nnn 個戰士
  • 兩種技能
    • 第一種,消費 xxx 點魔力值,消滅連續的 kkk 個戰士
    • 第二種,消費 yyy 點魔力值,選擇兩個連續戰士,戰斗力大的消滅戰斗力小的
  • 經過消費魔力的多次兩種操作,使得 aaa 數組變成 bbb 數組,問最少需要花費的魔力值是多少?
  • 若無法使 aaa 數組變成 bbb 數組,則輸出 ?1-1?1
  • 兩種操作圖示方框顏色是不相同的,希望能夠有好的閱讀體驗。

樣例輸入
5 2
5 2 3
3 1 4 5 2
3 5
樣例輸出
8

解釋

  • 原數組
  • 1、4 兩元素恰好長度為2,于是我們進行1操作,花費x(5)魔力值消滅連續的k(2)個戰士
  • 5、2兩元素的小值恰好是我們需要刪除的2,且單一2元素的長度為1不合適進行操作1,所以選擇操作2進行,花費魔力值3


  • 最后所花費的魔力值為 8 = 5 + 3

以上圖示符合樣例1的輸出情況

無解情況

樣例輸入
4 4
5 1 4
4 3 1 2
2 4 3 1
樣例輸出
-1

很明顯相同長度的兩個數組,元素的相對位置完全不同已經不能通過操作1、2進行改變了,因為操作1、2都沒有改變元素的相對位置。

疑問1

為什么不進行操作2?(那好,我們來嘗試下操作2消滅【1,4】的情況)

結果:
總花費:6魔力值>5魔力值(操作1)

歸納:這么說來操作2也不是不行,主要取決于我操作1和操作2的魔力值單次消耗情況和能否進行刪除(因為在這樣例中是恰好3>13>13>14<54<54<5,剛好小的都是需要刪除的)

想法:因此我們需要根據各種操作的魔力值消費情況進行貪心。

題解

  • 我們將該數組序列進行一下劃分,劃分為多個區間,這是為了根據不同區間的長度考慮進行操作1還是操作2,參考上面的疑問1。
  • 我們設區間長度為 LLL
  • L<kL< kL<k時,區間最大值大于左右端點,則無解,這是因為大值是你想要消滅的,你卻沒有辦法通過操作2進行消滅,如果區間最大值不大于左右端點, 魔法消耗就是 L * y,(兩個值消滅一個值,需要消滅長度為L,即L * y,這里不太理解可以看一下單調隊列)
  • L>=kL>=kL>=k時,區間最大值大于左右端點,那么我們可以進行操作2花費x的魔力值,消滅長度為k的戰士。
  • 注意:程序中途中的乘積會爆int

    代碼

    /* * n個戰士 * 兩種技能 1.x 魔力值 ,連續消滅k個戰士 2.y魔力值,選擇兩個連續戰士,戰斗力大的消滅戰斗力小的 * ai -> bi */ const int maxn = 2e5 + 50; int a[maxn], b[maxn]; LL x, k, y; int n, m; bool solve(int l, int r, LL &ans){bool judge = false; //當L< k時,區間最大值大于左右端點,則無解;if (l > r) return true;//我們區間的有解和無解是通過判斷區間中最大值的情況來解決的,因此我們需要尋找最大值int maxIndex = l;int L = r - l + 1; //區間長度FOR_1(i, l, r) if (a[i] > a[maxIndex]) maxIndex = i;//和左右端點值進行比較if (l - 1 >= 1 && a[l - 1] > a[maxIndex]) judge = true;if (r + 1 <= n && a[r + 1] > a[maxIndex]) judge = true;if (L < k && !judge) return false;//need removeint need = L % k;ans += need * y;L -= need;//疑問1的解決辦法if (y * k >= x) { ans += L / k * x; }else if(judge) { ans += L * y; } else { //其中長度k進行操作1,剩下進行操作2ans += (L - k) * y + x;}return true; } int main(){RD(n, m); RD(x, k, y);FOR_1(i, 1, n) RD(a[i]); FOR_1(i, 1, m) RD(b[i]);int i = 1, j = 1;LL ans = 0; //需要花費的魔力值//把b的部分都篩選出來,也就是b的下標j需要走到int p = 0;while(j <= m){while(i <= n && a[i] != b[j]) i++;if (i > n) return printf("-1\n") * 0; //b都沒全部得出a就沒了,說明存在問題不可能成立,直接-1就好if (!solve(p + 1, i - 1, ans)) return printf("-1\n") * 0;p = i, j++;}if (!solve(p + 1, n, ans)) return printf("-1\n") * 0;printf("%lld\n", ans);}

    總結

    以上是生活随笔為你收集整理的CF1380D.Berserk And Fireball 【2000】你值得学习的【思维】+【模拟】+【贪心】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。