原题传送门

一眼就能看出来这是一道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. MSF实现RID劫持和MSF实现PsExec执行命令

    msf实现rid劫持 rid劫持原理: 每个帐户都有一个指定的RID来标识它.与域控制器不同,Windows工作站和服务器会将大部分数据存储在HKLM\SAM\SAM\Domains\Account\ ...

  2. Power BI数据网关

      前言 你的组织中的用户可以访问本地数据(他们已经具有该数据的访问授权),但在这些用户可以连接到你的本地数据源之前,需要安装和配置本地数据网关. 该网关便于云中的用户与你的本地数据源相互进行快速安全 ...

  3. python __get__ & __set__

    目的:  提供类似java中的getter/setter的东西. (getter/setter的目的: 将属性方法化,使得属性的引用变得简单---尤其将来属性的读取/赋值有比较复杂的逻辑) 官方简明文 ...

  4. Centos6.8 安装dlib库时出错【升级gcc 到4.9.0以上】

    在centos6.8上安装dlib库时出现错误: 1.CMake must be installed to build the following extensions: dlib 没有安装CMake ...

  5. linux操作2

    第2天 linux操作系统的目录结构 bin   #可执行程序的安装目录,命令boot #系统启动引导目录dev #设备目录,deviceetc #软件配置文件目录home #用户的家目录lib #系 ...

  6. fiddler 修改

    很多新手学习fiddler抓包的同学们都会对https网站抓包难或者抓不起来的问题无所适从,想寻求解决办法,没问题,这节课就来解决你的疑问! 最典型的网站就是目前的百度网站了,百度在近些年采用了htt ...

  7. 前后端分离项目,标准json协议格式参考

      正常返回 { "code": 0, "data": [{ "cTime": "2018-11-19 14:46:16" ...

  8. 作业二 分布式版本控制系统Git的安装与使用

    第一步:Git bash配置 修改用户名和邮箱地址: $ git config --global user.name "zzj" $ git config --global use ...

  9. LeetCode 206 Reverse Linked List 解题报告

    题目要求 Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5-> ...

  10. TZOJ :2731: 存钱计划(二)

    描述 在TZC,WY存了钱,现在他要去买东西了.店很多,标记为1,2,3,4,5,6....但有的店之间有大路相连,而有的没有路.现在要由一个店到另一个店买东西,中途最少要经过多少个其它的店铺呢? 如 ...