P3957 [NOIP2017 普及组] 跳房子
cnblogs 2024-08-01 08:39:00 阅读 54
讲解 P3957 [NOIP2017 普及组] 跳房子。
首先注意到单调性,考虑二分,然后使用单调队列优化 dp 快速求出最大得分。
思路:
首先发现单调性,灵活性增加 \(x+1\) 的答案肯定不会比增加 \(x\) 的答案更劣。
那么可以二分求 \(g\),则机器人每次可以移动 \([\max(d-mid,1),d+mid]\) 这个区间内的距离,为了方便,设为 \([l,r]\)。
考虑动态规划求得能走到的最大分数,令 \(dp_i\) 表示走到第 \(i\) 个格子的最大分数,则状态转移方程为:
\[dp_i = s_i + \max\limits_{j=0}^{i-1} [x_i - r \le x_j] [x_j \le x_i - l] dp_j
\]
可以使用单调队列维护:
若当前队尾为 \(j\),且 \(x_j < x_i - r\),则这个 \(j\) 无法对 \(dp_i\) 造成贡献,直接不断弹出即可。
若当前队头为 \(j\),且 \(x_{j+1} \le x_i - l\),则这个 \(j+1\) 可以对 \(dp_i\) 造成贡献,不断插入即可。
因为要维护最大值,可以使用单调队列。
时间复杂度为 \(O(N \log W)\)。
完整代码:
<code>#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=5e5+10;
inline ll read(){
ll 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<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
ll n,d,k,l,r,head,tail,ans=-1;
ll a[N],b[N],dp[N],Q[N];
ll check(ll l,ll r){
head=1,tail=0;
ll sum=0,x=1,y=0;
for(int i=1;i<=n+1;i++){
if(i>1)
dp[i]=-1e18;
while(a[y+1]<=a[i]-l&&y<=n){
y++;
while(dp[y]>dp[Q[tail]]&&tail>=head)
tail--;
if(dp[y]>=-1e18)
Q[++tail]=y;
}
while(a[x]<a[i]-r&&x<=n){
if(Q[head]==x)
head++;
x++;
}
if(tail>=head)
dp[i]=b[i]+dp[Q[head]];
sum=max(sum,dp[i]);
}
return sum;
}
bool End;
int main(){
//open("A.in","A.out");
n=read(),d=read(),k=read();
for(int i=1;i<=n;i++){
a[i+1]=read();
b[i+1]=read();
}
l=0,r=1e9;
while(l<=r){
ll mid=(l+r)>>1;
if(check(max(d-mid,1ll),d+mid)>=k){
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
write(ans);
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。