「JSOI2015」送礼物

「JSOI2015」送礼物#

传送门

看到这题首先想到分数规划。

我们发现对于当前区间,如果它的最大值和最小值不是分居区间的两个端点的话,那么我们显然可以把两端多出去的部分舍掉,因为,在区间最大值最小值都不变的情况下,区间肯定是越短越优的。

但是要注意一点就是区间长度也是有下界的。

所以说我们就先处理所有区间长度为下界 L 的情况,然后再对区间长度位于 [L+1,R] 的区间做处理。

二分答案 mid ,假设当前区间是 [l,r] 那么就有:

maxi=lr{ai}mini=lr{ai}rl+kmid(maxi=lr{ai}+l×mid)(mini=lr{ai}+r×mid)k×mid

由于我们之前说过最大值和最小值一定分居区间的两个端点(是这里不妨假设 al 为最大值,另一种情况同理

那么就有:

(al+l×mid)(ar+r×mid)k×mid

所以我们可以令 fi=ai+i×mid ,然后枚举左端点,查询右端点的最小值即可(这个可以用 ST 表维护)

但是要记得判断右端点越界的情况。

参考代码:

Copy
#include <algorithm> #include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout) using namespace std; template < class T > inline void read(T& s) { s = 0; int f = 0; char c = getchar(); while ('0' > c || c > '9') f |= c == '-', c = getchar(); while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar(); s = f ? -s : s; } const int _ = 5e4 + 5; const double eps = 1e-7; int n, k, L, R, a[_], lg[_]; int mn[18][_], mx[18][_]; double f[18][_]; inline int query_mn(int l, int r) { int x = lg[r - l + 1]; return min(mn[x][l], mn[x][r - (1 << x) + 1]); } inline int query_mx(int l, int r) { int x = lg[r - l + 1]; return max(mx[x][l], mx[x][r - (1 << x) + 1]); } inline double query(int l, int r) { int x = lg[r - l + 1]; return min(f[x][l], f[x][r - (1 << x) + 1]); } inline bool chk(double mid) { for (rg int i = 1; i <= n; ++i) f[0][i] = a[i] + mid * i; for (rg int i = 1; i <= lg[n]; ++i) for (rg int j = 1; j + (1 << i) - 1 <= n; ++j) f[i][j] = min(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]); double res = -2e9; for (rg int i = 1; i + L <= n; ++i) res = max(res, f[0][i] - query(i + L, min(i + R - 1, n))); return res >= k * mid; } inline bool check(double mid) { if (chk(mid)) return 1; reverse(a + 1, a + n + 1); if (chk(mid)) return 1; return 0; } inline void solve() { read(n), read(k), read(L), read(R); for (rg int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1; for (rg int i = 1; i <= n; ++i) read(a[i]), mn[0][i] = mx[0][i] = a[i]; for (rg int i = 1; i <= lg[n]; ++i) for (rg int j = 1; j + (1 << i) - 1 <= n; ++j) { mn[i][j] = min(mn[i - 1][j], mn[i - 1][j + (1 << (i - 1))]); mx[i][j] = max(mx[i - 1][j], mx[i - 1][j + (1 << (i - 1))]); } double ans = -2e9; for (rg int i = 1; i + L - 1 <= n; ++i) ans = max(ans, 1.0 * (query_mx(i, i + L - 1) - query_mn(i, i + L - 1)) / (L + k - 1)); double l = 0, r = 1000; while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) l = mid; else r = mid; } printf("%.4lf\n", max(ans, l)); } int main() { #ifndef ONLINE_JUDGE file("cpp"); #endif int T; read(T); while (T--) solve(); return 0; }
posted @   Sangber  阅读(146)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
点击右上角即可分享
微信分享提示
CONTENTS