洛谷P3957 跳房子

2021-08-20 00:08:11 字數 1810 閱讀 6972

普及組的題。。。

我不會。。。 題目

思路很簡單,就是二分答案+dp+單調佇列(線段樹也可以),但是要注意細節,乙個細節錯了,一半分數就沒了。

引用洛谷上某大佬的一段話:

發現答案的可行區間是單調的,所以二分答案,容易推出f[i]表示到達第i個格仔的最大值,列舉上一步跳了多少來轉移

然後仔細觀察可以發現對於乙個狀態,如果有比他後面的狀態比他答案大的話,顯然不會優..於是可以單調佇列進行優化

但是考慮對於乙個點,他前面和他距離小於d-g的點是轉移不到的,如果直接得出某個f[i]後就將他放進佇列顯然是錯誤的

考慮維護乙個指標,表示當前最前面的乙個沒有加入單調佇列的元素,當且僅當當前節點和他相差》=d-g的時候就讓這個元素進隊

顯然這個指標也是單調的,也可以得出每個點在一次check中最多被指標指向一次;

處理完之後在一遍pop將所有和當前點距離》d+g的元素出隊,取隊首轉移就可以了..算是一道不難不簡單的套路題qwq

線段樹:

#include

using

namespace

std;

typedef

long

long ll;

const

int n=500003;

const ll p=-1999999999;

int n,d,k,i,ans,l,r,x[n],a[n],mid;

ll seg[n*4];

inline

int read()while (c<'0' || c>'9');

while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();

return flag*x;

}void build(int t,int l,int r)

void add(int t,int l,int r,int x,int val)

int mid=l+r>>1;

if (x<=mid) add(t<<1,l,mid,x,val);

else add(t<<1|1,mid+1,r,x,val);

seg[t]=max(seg[t<<1],seg[t<<1|1]);

}ll query(int t,int l,int r,int x,int y)

int check(int mid)

if (s>=k) return

1; }

return0;}

int main()

printf("%d",ans);

}

單調佇列:

#include

using

namespace

std;

const

int n=500003;

typedef

long

long ll;

ll x[n],s[n],f[n];

int n,k,i,q[n],h,t,d,l,r,ans,mid;

int read()while(c<48||c>57);

do x=(x<<1)+(x<<3)+(c^48),c=getchar();while(c>=48&&c<=57);

return f*x;

}void push(int x)

bool check(int g)

return0;}

int main()

printf("%d",ans);

}

洛谷P3957 跳房子

跳房子,也叫跳飛機,是一種世界性的兒童遊戲,也是中國民間傳統的體育遊戲之一。跳房子的遊戲規則如下 在地面上確定乙個起點,然後在起點右側畫 n 個格仔,這些格仔都在同一條直線上。每個格仔內有乙個數字 整數 表示到達這個 格仔能得到的分數。玩家第一次從起點開始向右跳,跳到起點右側的乙個格仔內。第二次再從...

洛谷P3957 跳房子

普及組的題.填坑來了。當年的我一眼二分 dp,現在都佩服起自己來了.然後我們就寫個二分,在check裡面寫單調佇列優化dp即可。然後就a了.1 include 2 include 3 include 4 5 typedef long long ll 6 const int n 500010 7 co...

題解 P3957 跳房子

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