原题传送门

一眼就能看出来这是一道dp题

显而易见每次操作的右端点一定是n,每株玉米被拔高的次数随位置不下降

用f(i,j) 表示以第i 株玉米结尾它被拔高了j 次的最长序列长度。

\(f(i,j)=Max(f(p,q)+1)(0<=p<i,0<=q<j,a_p+q<a_i+j\)]

复杂度是\(O(n^2k^2)\)

显然过不了这题

用d(i, j) 表示到目前为止结尾玉米被拔高了i 次高度为j的最长序列长度。

我们需要不断更新这个表(当然不会下降) ,并查询二维前缀最大值。

这珂以用二维树状数组来维护

复杂度\(O(n \log n k \log k)\)

#include <bits/stdc++.h>
#define getchar nc
#define N 10005
#define K 505
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
int n,k,tr[N][K],h[N],mx,ans=0;
inline int lb(register int x)
{
return x&(-x);
}
inline int query(register int x,register int y)
{
int res=0;
for(register int i=x;i;i-=lb(i))
for(register int j=y;j;j-=lb(j))
res=Max(tr[i][j],res);
return res;
}
inline void update(register int x,register int y,register int v)
{
for(register int i=x;i<=mx+k;i+=lb(i))
for(register int j=y;j<=k+1;j+=lb(j))
tr[i][j]=Max(tr[i][j],v);
}
int main()
{
n=read(),k=read();
for(register int i=1;i<=n;++i)
{
h[i]=read();
mx=Max(mx,h[i]);
}
for(register int i=1;i<=n;++i)
for(register int j=k;j>=0;--j)
{
int x=query(h[i]+j,j+1)+1;
ans=Max(ans,x);
update(h[i]+j,j+1,x);
}
write(ans);
return 0;
}

这已经能过这题了,但我们还珂以继续优化

我们珂以发现每次树状数组查询都有大量重复计算

所以珂以变成一维树状数组

#include <bits/stdc++.h>
#define getchar nc
#define N 10005
#define K 505
#define V 5005
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
int n,k,ans,h[N],f[N][K];
struct BinaryIndexTree{
int maxx[V];
inline void update(register int pos,register int v)
{
++pos;
for(register int i=pos;i<=V-1;i+=i&(-i))
maxx[i]=Max(maxx[i],v);
}
inline int query(register int pos)
{
int res=0;
++pos;
for(register int i=pos;i;i-=i&(-i))
res=Max(res,maxx[i]);
return res;
}
}tr1[K];
struct BinaryIndexTree2{
int maxx[K];
inline void update(register int pos,register int v)
{
++pos;
for(register int i=pos;i<=k+1;i+=i&(-i))
maxx[i]=Max(maxx[i],v);
}
inline int query(register int pos)
{
int res=0;
++pos;
for(register int i=pos;i;i-=i&(-i))
res=Max(res,maxx[i]);
return res;
}
}tr2[K+V];
int main()
{
n=read(),k=read();
for(register int i=1;i<=n;++i)
h[i]=read();
for(register int i=1;i<=n;++i)
for(register int j=0;j<=k;++j)
{
int tmp1=tr1[j].query(h[i]),tmp2=tr2[h[i]+j].query(j);
f[i][j]=Max(tmp1,tmp2)+1,ans=Max(ans,f[i][j]);
tr1[j].update(h[i],f[i][j]),tr2[h[i]+j].update(j,f[i][j]);
}
write(ans);
return 0;
}

【题解】Luogu P3287 [SCOI2014]方伯伯的玉米田的更多相关文章

  1. 洛谷 P3287 - [SCOI2014]方伯伯的玉米田(BIT 优化 DP)

    洛谷题面传送门 怎么题解区全是 2log 的做法/jk,这里提供一种 1log 并且代码更短(bushi)的做法. 首先考虑对于一个序列 \(a\) 怎样计算将其变成单调不降的最小代价.对于这类涉及区 ...

  2. 洛谷P3287 [SCOI2014]方伯伯的玉米田(树状数组)

    传送门 首先要发现,每一次选择拔高的区间都必须包含最右边的端点 为什么呢?因为如果拔高了一段区间,那么这段区间对于它的左边是更优的,对它的右边会更劣,所以我们每一次选的区间都得包含最右边的端点 我们枚 ...

  3. P3287 [SCOI2014]方伯伯的玉米田

    首先可以证明,一定存在一种最优解,每次选择的区间结尾都是 \(n\).因为如果某一个区间结尾不是 \(n\),将其替换成 \(n\) 仍然保持单调不下降.接着都按这个策略拔高玉米. 令 \(f_{i, ...

  4. bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化

    3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 314  Solved: 132[Submit][Sta ...

  5. bzoj 3594: [Scoi2014]方伯伯的玉米田

    3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MB Submit: 1399  Solved: 627 [Submit][ ...

  6. [SCOI2014]方伯伯的玉米田 题解(树状数组优化dp)

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  7. [SCOI2014]方伯伯的玉米田

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  8. BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  9. BZOJ3594 [Scoi2014]方伯伯的玉米田 【树状数组优化dp】

    题目链接 BZOJ3594 题解 dp难题总是想不出来,, 首先要观察到一个很重要的性质,就是每次拔高一定是拔一段后缀 因为如果单独只拔前段的话,后面与前面的高度差距大了,不优反劣 然后很显然可以设出 ...

随机推荐

  1. Java设计模式系列之装饰者模式

    装饰者模式的定义 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案  装饰者模式的UML类图 一般来说装饰者模式有下面几个参与者: Component:装饰者和被装饰者共同 ...

  2. java后端实习,从最简单的crud做起

    现在就是做ssm框架下的sql语句,主要是select语句,sql语句没什么难的,孰能生巧,趁此机会,把自己的sql基础打扎实,也是一种实习的经验. 1.在子查询中字段的类型不相容怎么办? cast函 ...

  3. 19. vue的原理

    vue:原理1 => Object.defineProperty 当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Obj ...

  4. html5与css 1. web标准及组成

    学习目标 1.本专业介绍.HTML相关概念,HTML发展历史 2.WEB标准,W3C/WHATWG/ECMA相关概念 3.相关软件的应用以及站点的创建 4.HTML基本结构和HTML语法 5.HTML ...

  5. java学习之路--StringBuffer常见的功能和实例

    ---恢复内容开始--- 储存 StringBuffer append();将指定数据作为参数添加到已有数据尾处 StringBuffer insert(index,数据):可以将数据插到指定的ind ...

  6. 布局fixed和sticky

    sticky非常非常非常好用怎么用看代码: 这里为什么没有设置高度呢,因为这个高度应该是浏览器高度,浏览器高度在时刻变化怎么办? js处理: 此JS里面会有执行方法一步一步看 这个里面有JS方法 这个 ...

  7. [No000018A]改善C#程序的建议11-20

    建议11:区别对待 == 和Equals CLR中将“相等性”分为两类:1.值相等性:两个变量包含的数值相等.2.引用相等性:两个变量引用的是内存中的同一个对象. 但并不是所有的类型的比较都是按照其本 ...

  8. Chrome 调试技巧

    Chrome 调试技巧 1.alert 这个不用多说了,不言自明. 可参考:https://www.cnblogs.com/Michelle20180227/p/9110028.html 2.cons ...

  9. Redis的数据结构之List

    存储list: ArrayList使用数组方式 LinkedList使用双向链接方式 双向链接表中增加数据 双向链接表中删除数据 存储list常用命令 两端添加 两端弹出 扩展命令 lpush 方式添 ...

  10. Ubuntu上Qt之简单图片浏览器

     >>主要功能: (1)图片切换浏览,上一张/下一张. (2)图片放大.缩小.包括两种机制:鼠标滚轮和按钮放大/缩小. (3)图片自动循环播放,间隔2s.点击播放后,其他操作均无效,直至点 ...