QwQ被普及组的题折磨的死去活来。

硬是卡线段树,没卡过QwQ

oi生涯,第一道正经的单调队列dp题

进入正题

题目大意:

其中\(n \le 500000\)

看到这个题的第一感觉就是二分金币数

很显然,如果\(mid\)可以,那么\(mid+1\)一定可以

但是QwQ

不要想\(nlog^2n\)了(卡了一下午没卡过去)

首先考虑裸的\(dp\)

\(dp[i]=max(dp[j])+val[i]\)



其中\(mindis<=|dis[i]-dis[j]|<=maxdis\)

这种做法应该是\(O(n^2logn)\)的

这里就不放代码了

取max的过程可以用线段树来优化QwQ虽然和暴力一个分 但是我只写了这种暴力。。。放一波代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath> using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 1000010; int x[maxn],val[maxn];
int n,d,k;
int dp[maxn],f[4*maxn];
int add[4*maxn]; void up(int root)
{
f[root]=max(f[2*root],f[2*root+1]);
} void pushdown(int root,int l,int r)
{
if (add[root])
{
add[2*root+1]=add[root*2]=add[root];
f[2*root]=add[root];
f[2*root+1]=add[root];
add[root]=0;
}
} void build(int root,int l,int r)
{
add[root]=0;
if (l==r)
{
f[root]=-1;
return;
}
int mid =(l+r) >> 1;
build(2*root,l,mid);
build(2*root+1,mid+1,r);
up(root);
} void update(int root,int l,int r,int x,int y,int p)
{
if (l>r || x>y) return;
if (x<=l && r<=y)
{
add[root]=p;
f[root]=p;
return;
}
int mid = (l+r) >>1;
pushdown(root,l,r);
if (x<=mid) update(2*root,l,mid,x,y,p);
if (y>mid) update(2*root+1,mid+1,r,x,y,p);
up(root);
} int query(int root,int l,int r,int x,int y)
{
if (l>r || x>y) return -1;
if (x<=l && r<=y)
{
return f[root];
}
pushdown(root,l,r);
int mid = (l+r) >> 1;
int ans=0;
if (x<=mid) ans=max(ans,query(2*root,l,mid,x,y));
if (y>mid) ans=max(ans,query(2*root+1,mid+1,r,x,y));
return ans;
} bool check(int min1,int max1)
{
build(1,1,n);
memset(f,-1,sizeof(f));
memset(dp,-1,sizeof(dp));
int l=1,r=1;
//int beg=1;
dp[1]=0;
//cout<<1<<endl;
for (int i=2;i<=n+1;i++)
{
//cout<<1<<endl;
while (x[i]-x[r] >= min1) update(1,1,n,r,r,dp[r]),r++;
while (x[i]-x[l]>max1) update(1,1,n,l,l,-1),l++;
//if (l>r) continue;
//cout<<1<<endl;
int tmp = query(1,1,n,1,n);
if (tmp!=-1)
{
dp[i]=max(dp[i],tmp+val[i]);
}
}
int mx=-1e9;
for (int i=1;i<=n+1;i++) mx=max(dp[i],mx);
//for (int i=1;i<=n+1;i++) cout<<dp[i]<<" ";
// cout<<endl;
if (mx>=k) return true;
else return false;
} int main()
{
n=read(),d=read(),k=read();
for (int i=2;i<=n+1;i++) x[i]=read(),val[i]=read();
int l=1,r=1e9;
int ans=0;
while (l<=r)
{
int mid =(l+r) >> 1;
if (check(max(d-mid,1),d+mid)) r=mid-1,ans=mid;
else l=mid+1;
//cout<<l<<" "<<r<<endl;
}
if (ans==0) ans=-1;
cout<<ans<<endl;
return 0;
}

真正的正确做法 是使用单调队列优化

单调队列是什么呢?

是一个队列 对,队列中的元素都是单调的

就比如说\(3,2,1\)

单调队列在维护的时候有两个注意:

1.新进来元素,会将他之前连续的比他小的元素代替掉,直到遇到一个大的,或者队列为空 (可以理解为过期晚,决策更优秀)

2.注意\(head\)和\(tail\)的大小和加减

直接上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long using namespace std; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 1000010; ll x[maxn],val[maxn];
ll n,d,k;
ll dp[maxn];
ll q[maxn];
ll t[maxn];
ll l=1,r=1;
ll head=1,tail=0; void push(int now,ll min1,ll max1)
{
while (x[now]-x[r]>=min1)
{
while (dp[r]>q[tail] && head<=tail) q[tail]=t[tail]=0,tail--;
q[++tail]=dp[r];
t[tail]=x[r];
r++;
}
while (x[now]-t[head]>max1 && head<=tail) t[head]=0,q[head++]=0;
}
bool check(ll min1,ll max1)
{
memset(dp,0xdf,sizeof(dp));
l=1,r=1;
dp[1]=0;
head=1,tail=0;
for (int i=2;i<=n+1;++i)
{
push(i,min1,max1);
if (head<=tail)
{
dp[i]=max(dp[i],q[head]+val[i]);
}
}
ll mx=-1e9;
for (int i=1;i<=n+1;i++) mx=max(dp[i],mx);
if (mx>=k) return true;
else return false;
} int main()
{
n=read(),d=read(),k=read();
for (int i=2;i<=n+1;i++) x[i]=read(),val[i]=read();
ll l1=1,rr=6e9;
ll ans=0;
while (l1<=rr)
{
ll mid =(l1+rr) >> 1;
if (check(max(d-mid,(long long)1),d+mid)) rr=mid-1,ans=mid;
else l1=mid+1;
//cout<<l<<" "<<r<<endl;
}
if (ans==0) ans=-1;
cout<<ans<<endl;
return 0;
}

洛谷luogu3957跳房子(单调队列优化)的更多相关文章

  1. 滑动窗口-洛谷T1866(单调队列)

    咕咕咕 单调队列板子题 一.基本 1.单调队列: 特殊的双端队列,内部元素.分为最大队列(单调递增)和最小队列(单调递减)两种 二.应用 本题中:大部分单调队列优化的动态规划问题都和定长连续子区间的最 ...

  2. NOIP2017 PJ 跳房子 —— 单调队列优化DP

    题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一.跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画n个格子,这些格子都在同一条直线上.每个格子内有一个 ...

  3. 洛谷 U4792 Acheing 单调队列

    U4792 Acheing 5通过 43提交 题目提供者Acheing 标签 难度尚无评定 提交 最新讨论 暂时没有讨论 题目背景 题目并没有什么含义,只是想宣传一下自己的博客,Acheing.com ...

  4. 【洛谷】【单调队列】P2032 扫描

    [题目描述:] 有一个 1 ∗ n 的矩阵,有 n 个正整数. 现在给你一个可以盖住连续的 k 的数的木板. 一开始木板盖住了矩阵的第 1 ∼ k 个数,每次将木板向右移动一个单位,直到右端与第 n ...

  5. 洛谷P2827 蚯蚓(单调队列)

    题意 初始时有$n$个蚯蚓,每个长度为$a[i]$ 有$m$个时间,每个时间点找出长度最大的蚯蚓,把它切成两段,分别为$a[i] * p$和$a[i] - a[i] * p$,除这两段外其他的长度都加 ...

  6. P1091 合唱队形题解(洛谷,动态规划LIS,单调队列)

    先上题目 P1091 合唱队形(点击打开题目) 题目解读: 1.由T1​<...<Ti​和Ti​>Ti+1​>…>TK​可以看出这题涉及最长上升子序列和最长下降子序列 2 ...

  7. 单调队列优化dp

    洛谷p3800(单调队列优化DP) 题目背景 据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了. 然而当时灵梦在Power达到MAX之前,不具有“上线收点”的能力,所以她想要知道 ...

  8. 洛谷P3975 跳房子 [DP,单调队列优化,二分答案]

    题目传送门 跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一 ...

  9. 2018.09.26洛谷P3957 跳房子(二分+单调队列优化dp)

    传送门 表示去年考普及组的时候失了智,现在看来并不是很难啊. 直接二分答案然后单调队列优化dp检验就行了. 注意入队和出队的条件. 代码: #include<bits/stdc++.h> ...

随机推荐

  1. js基本数据类型之间的转换

    常见五大基本数据类型 1.number 2.string 3.boolean 4.undefined 5.null 一.转换为string ①调用toString() 方法 因为null和undefi ...

  2. 性能测试工具JMeter 基础(一)—— 安装、配置环境变量

    JMeter下载 下载地址:https://jmeter.apache.org/download_jmeter.cgi 下载完成后解压后可直接使用,不用进行安装 环境变量配置 新增变量名:JMETER ...

  3. (八)羽夏看C语言——C番外篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  4. SAR总结

    1.星载InSAR技术简介 星载合成孔径雷达干涉测量(InSAR)是一种用于大地测量和遥感的雷达技术.InSAR使用两个或多个SAR图像,利用返回卫星的波的相位差来计算目标地区的地形.地貌以及表面的微 ...

  5. CSP-J&S 2020挂分记

    应该是退役记 OI 是一门玄学--考后有感 Day -inf 找各科老师请假备考,看着我倒一倒二的好成绩分纷劝我放弃竞赛,成功请到了假. Day -1 怎么莫名其妙大家都在学些奇怪的东西? 跟风写了一 ...

  6. VUE001. 拖动div盒子(自定义指令v-directives)

    拖动div是一个逻辑很简单的需求,监听容器的鼠标按下松开的事件,执行函数通过DOM改变标签的CSS偏移量. 在VUE构建的项目中,通过标签的 @mousedown 和 @mouseup 赋予行为事件, ...

  7. JavaScript深拷贝实现方式

    1.递归 function deepCope (obj) { // 要拷贝的数据为引用类型属性(数组或对象) if (obj && typeof obj === 'object') { ...

  8. 在 vue-cli 项目中 使用elementUI 的“自定义主题”功能

    1.安装elementUI $ npm i element-ui -S 2.安装主题工具 npm i element-theme -g 3.安装chalk主题 npm 安装 npm i element ...

  9. C# .NET Core 3.1 中 AssemblyLoadContext 的基本使用

    C# .NET Core 3.1 中 AssemblyLoadContext 的基本使用 前言 之前使用 AppDomain 写过一个动态加载和释放程序的案例,基本实现了自己"兔死狗烹&qu ...

  10. 【转载】linux 工作队列上睡眠的认识--不要在默认共享队列上睡眠

    最近项目组做xen底层,我已经被完爆无数遍了,关键在于对内核.驱动这块不熟悉,导致分析xen代码非常吃力.于是准备细细的将 几本 linux 书籍慢慢啃啃. 正好看到LINUX内核设计与实现,对于内核 ...