您的位置:首页 > Web前端 > JavaScript

BZOJ4850: [Jsoi2016]灯塔

2017-06-06 18:22 211 查看
BZOJ4850

很容易发现sqrt(|i−j|)很多情况下都是相等的。

那么就可以考虑分块。(题目应该是hj≤hi+p−sqrt(|i−j|))

当sqrt(|i−j|)=x时,令Mx为所有满足sqrt(|i−j|)=x的j中,最大的hj值。

那么p>=Mx+sqrt(|i−j|)−hi

一开始直接将sqrt(|i−j|)=x四舍五入了。。显然错了。应该向上取整。

然后发现长度为1时,x=1,长度为2,3,4时,x=2,长度为5,6,7,8,9时,x=3……

那么(i−1)2+1到i2的sqrt(|i−j|)是相等的。就可以分块了。

对于每一块,用RMQ求出块内最大值,对于每一块,求出最大值即可。Ansi=Max(Mx+x−hi)

复杂度O(NN−−√)。只要打的不算太丑都能水过去。。QAQdsy垫底1.15s噢不能用线段树。。加个log就跑不过去了。

至于正解。。决策单调性整体二分什么的。。反正我不会

【代码】

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define N 100005
#define mod 1000000007
#define INF 0x7fffffff
using namespace std;
typedef long long ll;

ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}

int n,sum;
int h
,DP
[30],Bit
;

void RMQ()
{
int temp=(int)(log((double)n)/log(2.0));
for(register int i=1;i<=n;i++) Bit[i]=(int)(log((double)i)/log(2.0));
for(register int i=1;i<=n;i++)
DP[i][0]=h[i];
for(register int j=1;j<=temp;j++)
for(register int i=1;i<=n;i++)
if(i+(1<<j)<=n) DP[i][j]=max(DP[i][j-1],DP[i+(1<<(j-1))][j-1]);
}
int Query(int L,int R)
{
int k=Bit[R-L+1];
return max(DP[L][k],DP[R-(1<<k)+1][k]);
}

void Solve(int x)
{
int i=1,j=x-1,ans=0;
while(1)
{
int len=i*i-(i-1)*(i-1);
int jj=j-len+1;jj=max(jj,1);
if(jj>j) break;
int mx=Query(jj,j);
ans=max(ans,mx-h[x]+i);
if(jj==1) break;j=jj-1;i++;
}
i=1,j=x+1;
while(1)
{
int len=i*i-(i-1)*(i-1);
int jj=j+len-1;jj=min(jj,n);
if(jj<j) break;
int mx=Query(j,jj);
ans=max(ans,mx-h[x]+i);
if(jj==n) break;j=jj+1;i++;
}
printf("%d\n",ans);
}

int main()
{
n=read();
for(register int i=1;i<=n;i++) h[i]=read();
RMQ();
for(register int i=1;i<=n;i++) Solve(i);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: