• BZOJ_2216_[Poi2011]Lightning Conductor_决策单调性


    BZOJ_2216_[Poi2011]Lightning Conductor_决策单调性

    Description


    已知一个长度为n的序列a1,a2,...,an。
    对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))

    Input

    第一行n,(1<=n<=500000)
    下面每行一个整数,其中第i行是ai。(0<=ai<=1000000000)

    Output

    n行,第i行表示对于i,得到的p

    Sample Input

    6
    5
    3
    2
    4
    2
    4

    Sample Output

    2
    3
    5
    3
    5
    4


    首先有f[i]=max(a[j]+sqrt(|i-j|))-a[i]

    先考虑j<i的情况,然后在考虑j>i的情况。

    设j1<j2<i1<i2,j2转移i1比j1转移i1优,j1转移i2比j2转移i2优。

    那么上下加一下再展开可以得出这是错的,所以满足决策单调性。

    这个题比较良心卡出了我以前决策单调性代码的罢嗝。

    就是每次队首的l需要++,否则计算后面的时候会用到Q[l].l,而此时Q[l].l可能已经转移过了。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define N 500050
    typedef double f2;
    struct A {
        int l,r,p;
    }Q[N];
    int a[N],n;
    f2 f[N];
    f2 Y(int j,int i) {
        return a[j]+sqrt(i>j?i-j:j-i);
    }
    int find1(const A &a,int x) {
        int l=a.l,r=a.r+1;
        while(l<r) {
            int mid=(l+r)>>1;
            if(Y(x,mid)<=Y(a.p,mid)) l=mid+1;
            else r=mid;
        }
        return l;
    }
    int find2(const A &a,int x) {
        int l=a.l,r=a.r+1;
        while(l<r) {
            int mid=(l+r)>>1;
            if(Y(x,mid)>Y(a.p,mid)) l=mid+1;
            else r=mid;
        }
        return l-1;
    }
    int main() {
        scanf("%d",&n);
        int i,l=0,r=0;
        for(i=1;i<=n;i++) scanf("%d",&a[i]);
        for(i=1;i<=n;i++) {
            Q[l].l++;
            while(l<r&&Q[l].l>Q[l].r) l++;
            f[i]=max(0.0,Y(Q[l].p,i)-a[i]);
            if(l==r||Y(i,n)>Y(Q[r-1].p,n)) {
                while(l<r&&Y(i,Q[r-1].l)>Y(Q[r-1].p,Q[r-1].l)) r--;
                if(l==r) Q[r++]=(A){i,n,i};
                else {
                    int x=find1(Q[r-1],i);
                    Q[r-1].r=x-1; Q[r++]=(A){x,n,i};
                }
            }
        }
        l=r=0;
        for(i=n;i>=1;i--) {
            Q[l].r--;
            while(l<r&&Q[l].l>Q[l].r) l++;
            f[i]=max(f[i],Y(Q[l].p,i)-a[i]);
            if(l==r||Y(i,1)>Y(Q[r-1].p,1)) {
                while(l<r&&Y(i,Q[r-1].r)>Y(Q[r-1].p,Q[r-1].r)) r--;
                if(l==r) Q[r++]=(A){1,i,i};
                else {
                    int x=find2(Q[r-1],i);
                    Q[r-1].l=x+1; Q[r++]=(A){1,x,i};
                }
            }
        }
        for(i=1;i<=n;i++) {
            printf("%d
    ",(int)ceil(f[i]));
        }
    }
    
  • 相关阅读:
    DBLE快速开始
    RPM包直接安装MySQL
    初试DTLE-单向-聚合-分散复制
    使用 TiUP cluster 在单机上安装TiDB
    如何升级到MySQL8.0
    SpringBoot集成AOP操作日志
    IDEA常用插件
    JAVA中如何实现字符串的反转?
    mysql数据库忘记密码时如何修改密码
    二分查找算法
  • 原文地址:https://www.cnblogs.com/suika/p/9237906.html
Copyright © 2020-2023  润新知