[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]发射站的主要内容,如果未能解决你的问题,请参考以下文章

luogu1901 发射站

P1901-发射站

luogu 1901 发射站

保留活动中的片段状态

一些恶心的代码片段

NodeJS 警告:可能的事件发射器泄漏。添加了 11 个开放式侦听器