• [bzoj4850][Jsoi2016]灯塔


    来自FallDream的博客,未经允许,请勿转载,谢谢。

    JSOI的国境线上有N一座连续的山峰,其中第ii座的高度是hi??.为了简单起见,我们认为这N座山峰排成了连续一条
    直线.如果在第ii座山峰上建立一座高度为p(p≥0)的灯塔,JYY发现,这座灯塔能够照亮第jj座山峰,当且仅当满足如
    下不等式:hj≤hi+p-(是减号)sqrt(|i-j|)JSOI国王希望对于每一座山峰,JYY都能提供建造一座能够照亮全部其他山峰的灯
    塔所需要的最小高度.你能帮助JYY么?
    1< N ≤ 10^5
    0 < hi ≤ 10^9
     
    话说这个出题人非常的不走心 同bzoj2216 5年前的题 样例都不改就扔了一个假的公式出来。
    暴力比较显然,可以预处理rmq,然后根号枚举。
    考虑两个点j,k,那么显然一个点分别从两个点转移的情况都是一段区间,可以二分求出最小的满足从j转移比从k转移优的i。
    然后开一个单调队列,维护队列中两两相邻元素,前一个比后一个优的最小的i 单调递增。
    复杂度nlogn
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define getchar() (*S++)
    #define MN 500000
    #define INF 2000000000
    char B[1<<26],*S=B;
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
     
    int n,a[MN+5],top,tail,q[MN+5];
    double F[MN+5],G[MN+5],sq[MN+5];
    inline int My_abs(int x){return x<0?-x:x;}
    double Get(int x,int y){return a[x]+sq[My_abs(y-x)];}
     
    int Calc(int x,int y)
    {
        int l=y,r=n,mid,ans=INF;
        while(l<=r)
        {
            mid=l+r>>1;
            if(Get(y,mid)>=Get(x,mid)) ans=mid,r=mid-1;
            else l=mid+1;   
        }
        return ans;
    }
     
    void Solve(double*f)
    {
        top=0;tail=1;   
        for(register int i=1;i<=n;++i)
        {
            if(top<tail||a[i]>a[q[top]]) 
            {
                while(top>tail&&Calc(q[top],i)<=Calc(q[top-1],q[top])) --top; 
                q[++top]=i;
            }
            while(top>tail&&Calc(q[tail],q[tail+1])<=i) ++tail;
            f[i]=Get(q[tail],i)-a[i];
        }
    }
     
    int main()
    {
        fread(B,1,1<<26,stdin);
        n=read();
        for(int i=0;i<=n;++i) sq[i]=sqrt(i);
        for(int i=1;i<=n;++i) a[i]=read();
        Solve(F);
        for(int i=1;i<=n>>1;++i) swap(a[i],a[n+1-i]);
        Solve(G);
        for(int i=1;i<=n;++i) printf("%d
    ",max(0,(int)ceil(max(F[i],G[n+1-i]))));
        return 0;
    }
  • 相关阅读:
    希尔排序
    插入排序
    Unity创建一个简易的弹簧(弹动)效果
    看到个美到爆的菜单,忍不住扒下来~
    用avalon实现一个完整的todomvc(带router)
    页面动态加入<script>标签并执行代码
    一个简单粗暴的前后端分离方案
    常用的HTML5、CSS3新特性能力检测写法
    犀利的background-clip:text,实现K歌字幕效果
    用canvas开发H5游戏小记
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4850.html
Copyright © 2020-2023  润新知