zoukankan      html  css  js  c++  java
  • 【SPOJ】Lightning Conductor (dp+决策单调性)

    题意翻译

    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

    由 @枫林晚 提供翻译

    SOLUTION:

    这题卡常啊qaq ,960ms卡过。。卡了好久。。。

    关于dp方程的写法,看看其他的博客就行,主要是像联系决策单调性的写法

     当踢出队尾时:

     

    CODE:

    #include<bits/stdc++.h>
    #define RG register
    #define R RG int
    #define G if(++ip==iend)fread(ip=buf,1,N,stdin)
    #define calc(i,j) a[j]+sq[i-j]//计算函数值
    using namespace std;
      #define double long double
    const int N=5e5+9;
    char buf[N],*iend=buf+N,*ip=iend-1;
    int n,a[N],q[N],k[N];
    double p[N],sq[N];
    inline int read()
    {
    	int X=0; bool flag=1; char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
    	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
    	if(flag) return X;
    	return ~(X-1);
    }
    
    inline int in(){
       int x;x=read();return x;
    }
    inline void chkmx(RG double&x,RG double y){
        if(x<y)x=y;
    }
    inline int bound(int p,R x,R y){//二分临界值k
        R l=y+1,r=(n),m,ret=r+1;//控制二分上下界
        while(l<=r){
            m=(l+r)>>1;
            if(calc(m,x)<=calc(m,y))
                ret=m,r=m-1;
            else l=m+1;
        }
        return ret;
    }
    void work(){
        
        for(R h=1,t=0,i=1;i<=n;++i){
            while(h<t&&k[h]<=i)++h;//将已经不优的决策出队
            chkmx(p[i],calc(i,q[h]));//因为做两遍所以取max3
           /// while(h<t&&bound(t,q[t-1],q[t])>=bound(t,q[t],i))--t;//这么写就T了
            while(h<t&&k[t-1]>=bound(t,q[t],i))--t;//维护k单调
            k[t]=bound(t,q[t],i); q[++t]=i;
        }
    }
    int main(){
    
      // freopen("in.txt","r",stdin);
        n=in();
        R i,j;
       // cout<<n<<endl;
        for(i=1;i<=n;++i)
            a[i]=in(),sq[i]=sqrt(i);
      //  puts("###");
        work();
        for(i=1,j=n;i<j;++i,--j)//序列翻转
            swap(a[i],a[j]),swap(p[i],p[j]);
        work();
        for(R i=n;i;--i)//翻转过了所以要倒着输出
            printf("%d
    ",max((int)ceil(p[i])-a[i],0));
        return 0;
        
        
    }
    

      

  • 相关阅读:
    OpenCV 实现图像拼接例子
    XML 可扩展标记语言
    XML和YAML的区别与使用方法
    OpenCV 感兴趣区域ROI和logo添加技术
    OpenCV 详解掩膜mask
    OpenCV 读写xml和yml文件
    OpenCV 如何生成能在无OpenCV环境下运行的exe
    OpenCV 图像拼接和图像融合技术
    OpenCV 特征检测和特征匹配方法汇总
    OpenCV 图像矫正技术深入探讨
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11253981.html
Copyright © 2011-2022 走看看