[LuoguP1901]发射站
Posted -wallace-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LuoguP1901]发射站相关的知识,希望对你有一定的参考价值。
一个本题不太寻常的解法。(需要正解的可以pass)
貌似题解区没有这么做的,但可能是我眼瞎。
( ext{Part-I:核心思想})
对于每一个发射塔,左右都可能有发射的对象,即向左数第一个(H)的值大于自己本身(H)的值的塔,或向右数第一个(H)的值大于自己本身(H)的值的塔。
我们逐个考虑。设现在为第(i)个发射塔,要确定左边的发射的对象。
首先,没有的情况,即(i=1 ext{ 或 }maxlimits_{1le k<i}H_kle H_i) 时。
若有,那么......
[ exttt{Binary Search! 二分查找——}]
有人就要问了:(H)不满足单调性,怎么二分?
(H)虽然不满足单调性,但是,我们先令(L_x=maxlimits_{1le y<x} H_y),即(H_1,H_2,...,H_{x-1})的最大值,(L)一定满足单调性!
对于(L)的维护,由于是静态的,所以ST表
是个不错的工具。
部分代码如下:
inline void find_left(int p)
{//此处的L存的是结果!!!
//query_max(x,y) 查询的是max{h[x],h[x+1],...,h[y]}。
if(p==1||query_max(1,p-1)<=h[p]) {L[p]=-1;return;}
int l=1,r=p;
while(r-l>1)
{
int mid=(l+r)>>1;
if(query_max(mid,p-1)>h[p]) l=mid;
else r=mid;
}
L[p]=l; return;
}
关于右边同理。
( ext{Part-II:时间复杂度})
ST表
的建立:(O(nlog_2 n))一次二分:(O(log_2 n))(
ST表
的查询一次为(O(1)))
( herefore ext{时间复杂度为}O(3nlog_2 n))
( ext{Part-III:完整代码})
(需开O2)
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e6 + 5;
int dp[maxn][25];
int h[maxn],v[maxn];
int n;
inline void init()
{
register int i,j;
for(i=1;i<=n;i++)
dp[i][0]=h[i];
for(j=1;j < 22;j++)
for(i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
inline int query_max(int l,int r)
{
int temp=log2(r-l+1);
return max(dp[l][temp],dp[r-(1<<temp)+1][temp]);
}
inline int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return f*x;}
inline void write(int x){if(x<0){putchar('-');x=-x;}if(x>9)write(x/10);putchar(x%10+'0');return;}
int L[maxn],R[maxn];
long long ans[maxn];
inline void find_left(int p)
{
if(p==1||query_max(1,p-1)<=h[p]) {L[p]=-1;return;}
int l=1,r=p;
while(r-l>1)
{
int mid=(l+r)>>1;
if(query_max(mid,p-1)>h[p]) l=mid;
else r=mid;
}
L[p]=l; return;
}
inline void find_right(int p)
{
if(p==n||query_max(p+1,n)<=h[p]) {R[p]=-1;return;}
int l=p,r=n;
while(r-l>1)
{
int mid=(l+r)>>1;
if(query_max(p+1,mid)>h[p]) r=mid;
else l=mid;
}
R[p]=r; return;
}
signed main()
{
register int i;
scanf("%d",&n);
for(i=1;i<=n;i++) h[i]=read(),v[i]=read();
init();
for(i=1;i<=n;i++)
find_left(i),find_right(i);
for(i=1;i<=n;i++)
{
if(L[i]!=-1) ans[L[i]]+=v[i];
if(R[i]!=-1) ans[R[i]]+=v[i];
}
printf("%lld",*max_element(ans+1,ans+1+n));
return 0;
}
(OVER.)
以上是关于[LuoguP1901]发射站的主要内容,如果未能解决你的问题,请参考以下文章