可以发现每次都对后缀+1是不会劣的。考虑dp:设f[i][j]为前i个数一共+1了j次时包含第i个数的LIS长度。则f[i][j]=max(f[i][j-1],f[k][l]+1) (k<i,l<=j,a[i]+j>=a[k]+l)。容易发现这里是二维偏序,相当于查询(j,a[i]+j)左下部分的最大值,二维树状数组暴力维护,复杂度O(nklogklogv)。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 10010
#define M 510
#define V 5010
int n,m,a[N],f[N][M];
int tree[M][V+M];
void ins(int x,int y,int k)
{
for (;x<=m+;x+=x&-x)
for (int i=y;i<=;i+=i&-i)
tree[x][i]=max(tree[x][i],k);
}
int query(int x,int y)
{
int s=;
for (;x;x-=x&-x)
for (int i=y;i;i-=i&-i)
s=max(s,tree[x][i]);
return s;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3594.in","r",stdin);
freopen("bzoj3594.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
int t=;
for (int i=;i<=n;i++) a[i]=read();
for (int i=;i<=n;i++)
{
for (int j=;j<=m;j++)
{
if (j) f[i][j]=f[i][j-];
f[i][j]=max(f[i][j],query(j+,a[i]+j)+);
}
for (int j=;j<=m;j++)
ins(j+,a[i]+j,f[i][j]);
}
for (int i=;i<=n;i++) f[][m]=max(f[][m],f[i][m]);
cout<<f[][m];
return ;
}

  虽然看到题解清一色的都是二维BIT,仔细琢磨一下还是感觉自己原来的维护方法并没有假。容易发现f[i][j]>=f[i][j-1],那么k确定时l取值越大越好,所以两个限制至少有一个取等号。那么可以改为维护很多棵BIT,复杂度变为O(nk(logk+logv))。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 10010
#define M 510
#define V 5010
int n,m,a[N],f[N][M];
int tree1[M][V+M],tree2[V+M][M];
void ins1(int x,int k,int p){while (k<=) tree1[x][k]=max(tree1[x][k],p),k+=k&-k;}
void ins2(int x,int k,int p){while (k<=) tree2[x][k]=max(tree2[x][k],p),k+=k&-k;}
int query1(int x,int k){int s=;while (k) s=max(s,tree1[x][k]),k-=k&-k;return s;}
int query2(int x,int k){int s=;while (k) s=max(s,tree2[x][k]),k-=k&-k;return s;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3594.in","r",stdin);
freopen("bzoj3594.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
int t=;
for (int i=;i<=n;i++) a[i]=read();
for (int i=;i<=n;i++)
{
for (int j=;j<=m;j++)
{
if (j) f[i][j]=f[i][j-];
f[i][j]=max(f[i][j],max(query1(j,a[i]+j),query2(a[i]+j,j+))+);
}
for (int j=;j<=m;j++)
ins1(j,a[i]+j,f[i][j]),ins2(a[i]+j,j+,f[i][j]);
}
for (int i=;i<=n;i++) f[][m]=max(f[][m],f[i][m]);
cout<<f[][m];
return ;
}

BZOJ3594 SCOI2014方伯伯的玉米田(动态规划+树状数组)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. bzoj3594: [Scoi2014]方伯伯的玉米田--树状数组优化DP

    题目大意:对于一个序列,可以k次选任意一个区间权值+1,求最长不下降子序列最长能为多少 其实我根本没想到可以用DP做 f[i][j]表示前i棵,操作j次,最长子序列长度 p[x][y]表示操作x次后, ...

  7. bzoj3594: [Scoi2014]方伯伯的玉米田

    dp新优化姿势... 首先,当我们拔高时,一定右端点是n最优.因为如果右端点是r,相当于降低了r之后玉米的高度.显然n更优. 那么可以dp.dp[i][j]表示前i个拔高j次的LIS.dp[i][j] ...

  8. 2019.03.28 bzoj3594: [Scoi2014]方伯伯的玉米田(二维bit优化dp)

    传送门 题意咕咕咕 思路:直接上二维bitbitbit优化dpdpdp即可. 代码: #include<bits/stdc++.h> #define N 10005 #define K 5 ...

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

    我们发现任何最优解都可以是所有拔高的右端点是n,然后如果我们确定了一段序列前缀的结尾和在此之前用过的拔高我们就可以直接取最大值了然后我们在这上面转移就可以了,然后最优解用二维树状数组维护就行了 #in ...

随机推荐

  1. 9.14 DP合集水表

    9.14 DP合集水表 关键子工程 在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为 1. 2. --. N:这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某 ...

  2. 【MYSQL用户创建报错】ERROR 1396 (HY000): Operation CREATE USER failed for 'user1'@'%'

    原文参考自:http://blog.csdn.net/u011575570/article/details/51438841 1.创建用户的时候报错ERROR 1396 (HY000): Operat ...

  3. JS基础,课堂作业,成绩练习

    成绩练习 <script> var name = prompt("请输入学生姓名:"); var degree = parseInt(prompt("请输入学 ...

  4. Git之hotfix热修复分支

    1.假设你正在开发一个新功能, 需要新建一个new分支并切换: git checkout -b new 等价于 git branch new git checkout new 然后在这个new分支上已 ...

  5. hdu6447

    YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  6. 欢迎来怼第二周Scrum会议六(总第十三次)

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/25  17:19~17:35(总计16min).地点:东 ...

  7. 【Alpha】阶段第四次Scrum Meeting

    [Alpha]阶段第四次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 获取课程评论接口 增加课程接口 赵智源 整合前端进行部署 整合前端进行部署 肖萌威 编写 ...

  8. idea的快捷键(复制)

    IntelliJ Idea 常用快捷键列表 Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Sh ...

  9. KNY团队与“易校”小程序介绍

    一.团队介绍 “KNY”团队是软件工程专业中的一支充满了斗志,充满了自信的队伍,由三人组成,每个队员都在为我们共同一致的目标而努力:我们三个人的小程序的知识都相对薄弱,但我们不甘落后,一直在努力的学习 ...

  10. 基础算法学习2-dp

    一.算法题: 最大子阵 给定一个n×m 的矩阵 A,求A 中的一个非空子矩阵,使这个子矩阵中的元素和最大.其中,A 的子矩阵指在 A 中行和列均连续的一部分.输入格式输入的第一行包含两个整数 n,m( ...