zoukankan      html  css  js  c++  java
  • NOIP2017 跳房子题解

    题目链接

    题目描述:

    太长了不贴了。

    解题思路:

    不难想到二分g,判断一下,朴素的算法是n^2 * log(n)的。

    check()函数:

    O(n^2)做法:

    f[i]表示到第i个点的最大分数。

    f[i]=max(f[j])+s[i] (J满足x[j]+Max>=x[i],x[j]+Min<=x[i])

    O(n)的做法:

    单调队列优化,

    1.用一个指针now记录入栈的结点,当x[i]-x[now]>=Min进入循环,

    在循环的过程中去除无法到达的now,把合法的结点加入栈。

    2.将满足上述条件的情况下,去除x[pos[l]]+Max<x[i]的情况,

    如果l>r表示没有解。赋值为-INF,反之更新。

    代码:

    #include<bits/stdc++.h>
    #define ll long long 
    #define R register
    using namespace std;
    const int N=5e5+5;
    int n,d,k,s[N],x[N],ans=0x3f3f3f3f,f[N];
    int pos[N];
    inline int check(R int g)//二分g
    {
        //f[i] 表示 到第i个点 得到分数的最大值
        //f[i]=max(f[i],f[j]+s[i]);j满足   x[j]+Max>=x[i]
        //                            x[j]+Min<=x[i]
        memset(pos,0,sizeof(pos));
        memset(f,0,sizeof(f));
        R int Min=max(1,d-g);
        R int Max=d+g;
        R int l=1,r=0,now=0;
        if(Max<x[1])return 1;
        for(R int i=1;i<=n;i++)
        {
                while(x[i]-x[now]>=Min)
                {
                    if(f[now]<=-0x3f3f3f3f)
                    {
                        now++;
                        continue;
                    }
                    while(f[now]>=f[pos[r]]&&l<=r)r--;
                    pos[++r]=now;
                    now++;
                }
                while(x[pos[l]]+Max<x[i]&&l<=r)l++;
                if(l<=r)
                f[i]=f[pos[l]]+s[i];
                else
                f[i]=-0x3f3f3f3f;
                //printf("%d %d
    ",i,f[i]);
                if(f[i]>=k)return 0;
        }
        return 1;
    }
    int main(){
        R int l=0,r=0;
        scanf("%d%d%d",&n,&d,&k);
        for(R int i=1;i<=n;i++)
        scanf("%d%d",&x[i],&s[i]);
        r=x[n];
        while(l<r)
        {
            R int mid=(l+r)/2;
            if(check(mid))
            {
                l=mid+1;
            }
            else
            {
                r=mid;
                ans=min(ans,mid);
            }
        }
        if(ans==0x3f3f3f3f)
        printf("-1");
        else
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    新加坡
    android alt + /
    豌豆荚开源技术
    有意思的
    android view
    localstorage性能
    Android WebView使用基础
    关于hash
    Android 近百个项目的源代码,覆盖Android开发的每个领域
    10个经典的Android开源项目(附源码包)
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9883855.html
Copyright © 2011-2022 走看看