BZOJ3594 SCOI2014方伯伯的玉米田(动态规划+树状数组)
可以发现每次都对后缀+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方伯伯的玉米田(动态规划+树状数组)的更多相关文章
- BZOJ3594 [Scoi2014]方伯伯的玉米田 【树状数组优化dp】
题目链接 BZOJ3594 题解 dp难题总是想不出来,, 首先要观察到一个很重要的性质,就是每次拔高一定是拔一段后缀 因为如果单独只拔前段的话,后面与前面的高度差距大了,不优反劣 然后很显然可以设出 ...
- bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化
3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 314 Solved: 132[Submit][Sta ...
- [SCOI2014]方伯伯的玉米田 题解(树状数组优化dp)
Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...
- 洛谷P3287 [SCOI2014]方伯伯的玉米田(树状数组)
传送门 首先要发现,每一次选择拔高的区间都必须包含最右边的端点 为什么呢?因为如果拔高了一段区间,那么这段区间对于它的左边是更优的,对它的右边会更劣,所以我们每一次选的区间都得包含最右边的端点 我们枚 ...
- BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】
Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...
- bzoj3594: [Scoi2014]方伯伯的玉米田--树状数组优化DP
题目大意:对于一个序列,可以k次选任意一个区间权值+1,求最长不下降子序列最长能为多少 其实我根本没想到可以用DP做 f[i][j]表示前i棵,操作j次,最长子序列长度 p[x][y]表示操作x次后, ...
- bzoj3594: [Scoi2014]方伯伯的玉米田
dp新优化姿势... 首先,当我们拔高时,一定右端点是n最优.因为如果右端点是r,相当于降低了r之后玉米的高度.显然n更优. 那么可以dp.dp[i][j]表示前i个拔高j次的LIS.dp[i][j] ...
- 2019.03.28 bzoj3594: [Scoi2014]方伯伯的玉米田(二维bit优化dp)
传送门 题意咕咕咕 思路:直接上二维bitbitbit优化dpdpdp即可. 代码: #include<bits/stdc++.h> #define N 10005 #define K 5 ...
- [BZOJ3594] [Scoi2014]方伯伯的玉米田 二维树状数组优化dp
我们发现任何最优解都可以是所有拔高的右端点是n,然后如果我们确定了一段序列前缀的结尾和在此之前用过的拔高我们就可以直接取最大值了然后我们在这上面转移就可以了,然后最优解用二维树状数组维护就行了 #in ...
随机推荐
- MySQL数据库之安装,基本操作
一.基础部分 1.数据库是什么 之前所学,数据要永久保留,比如用户注册的用户信息,都是保存于文件,而文件只能存在于某一台机器上. 如果我们不考虑从文件中读取数据的效率问题,并且假设我们的程序所有的组件 ...
- docker基本的常用命令
- Qt 将字符串转成16进制显示
最近项目用到了需要将字符串转换成16进制显示.这玩意折腾了一上午. 首先,数据块内容 struct UserData { char Head[3] = {'X','J','J'}; char Flag ...
- Linux 安装Redis<集群版>(使用Mac远程访问)
阅读本文需要先阅读安装Redis<准备> 一 架构细节 所有的redis节点彼此互联(PING-PONG机制) 内部使用二进制协议优化传输速度和带宽 节点的fail是通过集群中超过半数的节 ...
- throttle(节流)和debounce(防抖)
防抖和节流都是用来控制频繁调用的问题,但是这两种的应用场景是有区别的. throttle(节流) 有一个调用周期,在一个很长的时间里分为多段,每一段执行一次.例如onscroll,resize,500 ...
- ExpressJS基础概念及简单Server架设
NodeJS Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.js 的包 ...
- ES6的新特性(6)——正则的扩展
正则的扩展 RegExp 构造函数 在 ES5 中,RegExp构造函数的参数有两种情况. 第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag). var regex = ne ...
- sip鉴权认证算法详解及python加密
1. 认证和加密 认证(Authorization)的作用在于表明自己是谁,即向别人证明自己是谁.而相关的概念是MD5,用于认证安全.注意MD5仅仅是个hash函数而已,并不是用于加密.因为ha ...
- 3. IP地址转换函数
一.字符串表示的IP地址需要被转化为整数(二进制数)方能使用 IPv4地址:点分十进制字符串 IPv6地址:十六进制字符串 有时(如记录日志),我们则要把整数(二进制数)表示的IP地址转化为可读的字符 ...
- sprint1_11.15燃尽图(第二天)
找相关的图片资料用于做点餐系统的界面 燃尽图: