洛谷P3957 跳房子
普及组的题.....填坑来了。
当年的我一眼二分+DP,现在都佩服起自己来了......
然后我们就写个二分,在check里面写单调队列优化DP即可。
然后就A了......
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 typedef long long LL; 6 const int N = 500010; 7 const LL INF = (1ll << 61); 8 9 int n, x[N]; 10 LL v[N], k; 11 12 int p[N], head, top; 13 LL f[N]; 14 15 inline bool check(int L, int R) { 16 memset(f, 0xcf, sizeof(f)); 17 LL ans = -INF; 18 f[0] = 0; 19 head = 1; 20 top = 0; 21 int pos_in = 0; 22 for(int i = 1; i <= n; i++) { 23 while(x[i] - x[pos_in] >= L) { 24 p[++top] = pos_in; 25 while(head < top && f[p[top]] > f[p[top - 1]]) { 26 p[top - 1] = p[top]; 27 top--; 28 } 29 pos_in++; 30 } 31 while(head <= top && x[i] - x[p[head]] > R) { 32 head++; 33 } 34 35 if(head <= top) { 36 f[i] = f[p[head]] + v[i]; 37 } 38 39 ans = std::max(ans, f[i]); 40 } 41 return ans >= k; 42 } 43 44 int main() { 45 int d; 46 LL sum = 0; 47 scanf("%d%d%lld", &n, &d, &k); 48 for(int i = 1; i <= n; i++) { 49 scanf("%d%lld", &x[i], &v[i]); 50 sum += std::max(v[i], 0ll); 51 } 52 if(sum < k) { 53 printf("-1"); 54 return 0; 55 } 56 57 int l = 0, r = std::max(x[n] - d, d), mid; 58 while(l < r) { 59 mid = (l + r) >> 1; 60 if(check(std::max(1, d - mid), d + mid)) { 61 r = mid; 62 } 63 else { 64 l = mid + 1; 65 } 66 } 67 68 printf("%d", r); 69 return 0; 70 }