原题传送门

一眼就能看出来这是一道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. Nest js 使用axios模块

    文档 let r = await this.http.get(`https://api.github.com/users/januwA`).toPromise().then(v => v.dat ...

  2. thinkphp5中使用phpmailer实现发送邮件功能(转载)

    一.开启SMTP服务(使用php发送邮件需要用到SMTP服务,这里以163邮箱的SMTP服务为例). 1.登录163邮箱,在首页上找到“设置”. 2.选择开启的服务,一般都全选,POP3/SMTP/I ...

  3. release git tag easy use

    #!/usr/local/env bash FLOW_VERSION=v2.0-rc-`date +"%Y-%m-%dT%H-%M-%S"` echo "version: ...

  4. js中级小知识5

    元素的属性 div.attributes是所有标签属性构成的数据集合 div.classList是所有class名构成的数组集合 在classList的原型链上可以看到add()和remove() 1 ...

  5. 转CB大佬的几个有用的MySQL知识

    1.find_in_set函数 find_in_set(str,strlist); str是一个字符串 strlist是字符串列表--一个有多个子链被“,”分开的字符串 有多种情况: a.str为nu ...

  6. 转载http协议

    转载自:https://blog.csdn.net/weixin_38051694/article/details/77777010 1.说一下什么是Http协议 对器客户端和 服务器端之间数据传输的 ...

  7. POJ 1426 - Find The Multiple - [DP][BFS]

    题目链接:http://poj.org/problem?id=1426 Given a positive integer n, write a program to find out a nonzer ...

  8. spring相关jar包

    spring.jar是包含有完整发布的单个jar 包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到 spring-m ...

  9. sx1278 手册参考

    记录下芯片的重要数据和内容,方便查阅,无代码实现 参考程序地址:http://www.pudn.com/Download/item/id/3070942.html  http://www.cirmal ...

  10. mybatis 转义

    当我们需要通过xml格式处理sql语句时,经常会用到< ,<=,>,>=等符号,但是很容易引起xml格式的错误,这样会导致后台将xml字符串转换为xml文档时报错,从而导致程序 ...