【BZOJ 2216】【POI 2011】Lightning Conductor

http://www.lydsy.com/JudgeOnline/problem.php?id=2216
学习了一下决策单调性。
这道题决策单调性比较明显,不详细证了。
对于一个决策i,如果在i之前的j处进行决策,那么i之后的决策都不可能在j之前。
利用决策单调性,可以维护每个决策点形成的单调栈,更新决策点也是利用单调栈的信息在原数组上二分。
这道题假设j<i,然后扫两遍就可以了,时间复杂度\(O(n\log n)\)
看网上的大爷都写得单调队列?整体二分?orz

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 500003;

int st[N], top, stn[N];

void solve(int n, int *a, int *f) {
    top = 0;
    for (int i = 1; i <= n; ++i) {
        int left = 1, right = top, mid;
        while (left < right) {
            mid = (left + right + 1) >> 1;
            if (stn[mid] <= i) left = mid;
            else right = mid - 1;
        }
        
        if (top) f[i] = max(ceil(sqrt(i - st[left])) + a[st[left]] - a[i], 0.0);
        while (top && stn[top] > i && sqrt(stn[top] - st[top]) + a[st[top]] < sqrt(stn[top] - i) + a[i]) --top;
        
        if (!top) {st[++top] = i; stn[top] = i + 1; continue;}
        
        left = max(i + 1, stn[top] + 1); right = n + 1;
        while (left < right) {
            mid = (left + right) >> 1;
            if (sqrt(mid - st[top]) + a[st[top]] < sqrt(mid - i) + a[i]) right = mid;
            else left = mid + 1;
        }
        
        if (left <= n) st[++top] = i, stn[top] = left;
    }
}

int a[N], n, f1[N], f2[N];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    solve(n, a, f1);
    reverse(a + 1, a + n + 1);
    solve(n, a, f2);
    reverse(f2 + 1, f2 + n + 1);
    
    for (int i = 1; i <= n; ++i) printf("%d\n", max(f1[i], f2[i]));
    return 0;
}

转载于:https://www.cnblogs.com/abclzr/p/6675047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值