P3957 跳房子 二分答案 dp 單調佇列

2022-08-12 21:33:20 字數 1260 閱讀 7232

前年pj沒去年難好吧

首先要發現這個答案是有單調性的。

這個很顯然了:氪金越多遊戲越容易玩,氪金越少越難。

然而也有界限:如果所有正數的和加起來還不夠需求,無解。

所以二分答案,考慮如何判定答案。

是人都知道要設乙個\(dp[i]\)表示跳前\(i\)個房子的最大分數。

50pts就很簡單的暴力轉移:

\[dp[i]=max(dp[j]+a[i]),j < i,lim_1

其實很大的暗示了:把\(a[i]\)拿出來就是:\(dp[i]=a[i]+max(dp[j])\)

單調佇列走一波,維護滑動視窗最大值!

不得不說這裡的單調佇列很難寫對。

我們弄乙個指標\(j\),當我們求\(dp[i]\)的時候就移動\(j\)到最近。

然後當我們詢問最大值的時候再考慮討論退役人員的彈出,得到最大值。

**:

#includeusing std::cin;

using std::cout;

using std::endl;

#define ll long long

const int maxn = 500005;

const int inf = 0x8f8f8f8f;

int a[maxn], dis[maxn];

int dp[maxn];

int n, d, k;

std::dequeq;// dan diao di jian

bool check(int g)

}*/while(j < i && dis[i] - dis[j] >= lim1)

j++;

}while(!q.empty() && dis[i] - dis[q.front()] > lim2) q.pop_front();

if(!q.empty()) dp[i] = dp[q.front()] + a[i];

}int ans = 0x8f8f8f8f;

for(int i = 1; i <= n; i++) ans = std::max(ans, dp[i]);// wrong here

return ans >= k;

}int main()

int left = 0, right = std::max(dis[n], d), ans = -1;

while(left <= right)

cout << ans << endl;

return 0;

}

P3957 跳房子 單調佇列,dp,二分

這就是之前普及組的第四題 有n個格仔,每個格仔有價值。機械人有固定的跳躍距離d,用k個金幣改進的話,就可以讓跳躍距離在d k到d k之間,不過至少要往前跳1個單位長度,每次都必須跳到格仔上。要求超過需要的價值求需要消耗的最少金幣。二分所需金幣數然後 dp,f i f i 表示跳到第i個格仔最大價值,...

滑動視窗 二分 P3957 跳房子

思路 dp i 表示到第 i 個格仔的最大得分,仔細思考後發現 f i 只能從他之前一段區間內的最大 f i 轉移過來,且隨著區域的後移不斷改變,滑動視窗維護再二分答案就好了。實現 滑動視窗的活動範圍 max d len 1 to d len 滑動視窗的移動 當最大值的位置超過了他能跳到的最遠距離,...

題解 P3957 跳房子

題目鏈結 題目大意 給定 n 個格仔離原點距離以及權值,初始單次移動距離只能為 d 你可以花費 g 枚金幣使得單次移動距離變為 max d g,1 d g 內任意整數,問獲得權值至少為 k 最少需要花費多少枚金幣 單調佇列 分析 顯而易見答案具有單調性,因為花費金幣越多機械人越靈活,花費金幣少的可行...