NC20227. [JSOI2016]灯塔
描述
输入描述
输入一行包含一个正整数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; }