noip2017普及组跳房子 (jump.cpp)

这个题目的主要思路就是二分答案找g值最小值

对于每种g值我们都计算一遍是否能够获得k分

在计算时采用dp dp的主要思路为在当前的g值下对于当前块dp[i] 为从起点跳到第i个块最多收益 显然转移方程 记所有能跳到i块的块为q[j] 则dp[i]=max(q[j])+第i块的权值

如果只用普通dp则时间复杂度为 O(n^2)

所以必须要用单调队列来使复杂度降为 O(n)则总复杂度为O(n*log(S总))


```
#include 
#define ll long long
using namespace std;
ll n,d,k,s[500001],a[500001],q[500001],m[500001],sum;//s[i]为第i块到起点的距离,a[i]为第i块的权值
//q,m为单调队列的两个参数 q存的是块的权值 m存的是块到起点的距离
bool check(ll g);//二分之后求解
int main(){
    cin>>n>>d>>k;
    for(int i=1;i<=n;i++){
        cin>>s[i]>>a[i];
        if(a[i]>0)sum+=a[i];//把所有正数累加
    }
    if(sum>1;
        if(check(mid)){
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    cout<maxx))head++;//如果前面单调队列中的块已经跳不到现在的块了则出队列
        if(head<=tail)dp[i]=q[head]+a[i];//找到最大值
        else dp[i]=-1000000000;//找不到说明没有块能跳到这个块
        if(dp[i]>=k)return 1;//如果跳到这个块就已经能达到题目要求分数则说明这个g值是成立的
    }
    return 0;
}
```


你可能感兴趣的:(noip2017普及组跳房子 (jump.cpp))