POI2012STU-Well

POI #Year2012 #二分

考虑二分答案,然后如果 |aiai1|>mid ,那么一定要提前操作掉,先把这种情况搞掉

然后考虑枚举一个位置变成 0 ,在上面的操作后,可以保证 |aiai1|mid ,那么这时还需要操
作的区间 [l,r]l,r 都随着 i 的增加而增加,维护这两个端点直接算答案

// Author: xiaruize
const int N = 1e6 + 10;
int n, m;
int a[N];
int s[N], sum[N];
int check(int x)
{
memcpy(s, a, sizeof(s));
int cnt = 0;
rep(i, 2, n) s[i] = min(s[i - 1] + x, s[i]);
per(i, n - 1, 1) s[i] = min(s[i], s[i + 1] + x);
rep(i, 1, n)
{
cnt += a[i] - s[i];
sum[i] = sum[i - 1] + s[i];
}
for (int i = 1, l = 1, r = 1; i <= n; i++)
{
while (r < n && (r - i + 1) * x < s[r + 1])
r++;
while (l < i && (i - l) * x >= s[l])
l++;
if (cnt + sum[r] - sum[l - 1] - x * ((i - l) * (i - l + 1) / 2 + (r - i) * (r - i + 1) / 2) <= m)
return i;
}
return -1;
}
void solve()
{
cin >> n >> m;
rep(i, 1, n) cin >> a[i];
int l = 0, r = 1e9;
pii res = {-1, -1};
while (l < r)
{
int mid = l + r >> 1;
int v = check(mid);
if (v == -1)
l = mid + 1;
else
{
r = mid;
res = {mid, v};
}
}
cout << res.second << ' ' << res.first << endl;
}
#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int testcase = 1;
// cin >> testcase;
while (testcase--)
solve();
#ifndef ONLINE_JUDGE
cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
return 0;
}

本文作者:xiaruize's Blog

本文链接:https://www.cnblogs.com/xiaruize/p/18156739

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   xiaruize  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起