列表

详情


NC20227. [JSOI2016]灯塔

描述

JSOI的国境线上有N一座连续的山峰,其中第i座的高度是hi,为了简单起见,我们认为这N座山峰排成了连续一条直线.如果在第i座山峰上建立一座高度为p(p≥0)的灯塔,JYY发现,这座灯塔能够照亮第j座山峰,当且仅当满足如下不等式:hj≤hi+p-sqrt(|i-j|)JSOI国王希望对于每一座山峰,JYY都能提供建造一座能够照亮全部其他山峰的灯塔所需要的最小高度.你能帮助JYY么?
1< N ≤ 10^5
0 < hi ≤ 10^9

输入描述

输入一行包含一个正整数N。
接下来N行,第i行包含一个正整数ℎi,表示第i座山峰的高度。

输出描述

第i行包含一个非负整数,表示在第i座山峰上修建灯塔所需要的最小高度Pi

示例1

输入:

6
5
3
2
4
2
4

输出:

2
3
5
3
5
4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 989ms, 内存消耗: 16072K, 提交时间: 2022-09-14 13:39:09

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define dep(i,a,b) for(register int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read(){
    ll f=1,x=0;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;
}
const int maxn=1e5+6;
int n,h[maxn],f[maxn][36],bit[maxn],blo;
void RMQ(){
    rep(i,1,n)f[i][0]=h[i];
    rep(j,1,blo)
        rep(i,1,n)
            if(i+(1<<j)<=n)f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
inline int query(int l,int r){
    int Len=bit[r-l+1];
    return max(f[l][Len],f[r-(1<<Len)+1][Len]);
}
void doit(int x){
    int i=1,j=x-1,ans=0;
    while(true){
        int len=i*i-(i-1)*(i-1),k=max(j-len+1,1);
        if(k>j)break;int Max=query(k,j);
        ans=max(ans,Max-h[x]+i);
        if(k==1)break;
        j=k-1;i++;
    }
    i=1,j=x+1;
    while(true){
        int len=i*i-(i-1)*(i-1),k=min(n,j+len-1);
        if(k<j)break;int Max=query(j,k);
        ans=max(ans,Max-h[x]+i);
        if(k==n)break;
        j=k+1;i++;
    }
    printf("%d\n",ans);
}

int main()
{
    n=read();
    blo=(int)(log((double)n)/log(2.0));
    rep(i,1,n)bit[i]=(int)(log((double)i)/log(2.0));
    rep(i,1,n)h[i]=read();
    RMQ();
    rep(i,1,n)doit(i);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 64ms, 内存消耗: 3180K, 提交时间: 2020-03-10 12:21:09

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
	int op,h;
}a[110000],b[110000];
int n,len;
int answer[110000];
bool cmp(node n1,node n2)
{
	if(n1.h!=n2.h) return n1.h<n2.h;
	return n1.op<n2.op;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i].h),a[i].op=i;
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++)
	if(a[i+1].h!=b[len].h)
	{
		if(a[i].op!=b[len].op) b[++len]=a[i];
		b[++len]=a[i+1];
	}
	len--;
	for(int i=1;i<=n;i++)
	{
		int cnt=a[i].op,sum=a[i].h,ans=0;
		for(int j=len;j>=1;j--)
		{
			if(b[len].h-b[j].h>=317) break;
			double num=(b[j].h-sum+sqrt(abs(b[j].op-cnt)));
			int tt=ceil(num);
			ans=max(ans,tt);
		}
		answer[cnt]=ans;
	}
	for(int i=1;i<=n;i++)
	printf("%d\n",answer[i]);
	return 0;
}

上一题