Codeforces 436D - Pudding Monsters(dp)
u1s1 这题数据范围有点迷惑啊……乍一看 \(\mathcal O(nm)\) 过不去,还以为是正解是 \(\mathcal O(n+m^2)\) 呢。
考虑 \(dp\),设 \(f_i\) 表示用前 \(i\) 个布丁,并且第 \(i\) 个布丁要么不动,要么向左移动能够覆盖的最多特殊格子数,再设 \(g_i\) 表示前 \(i\) 个布丁,并且第 \(i\) 个布丁的位置不发生变化所能覆盖的最多特殊格子数。
想好了 \(dp\) 状态,转移就水到渠成了:
- 对于 \(f_i\),要么第 \(i\) 个布丁不动,即 \(g_i\rightarrow f_i\),要么第 \(i\) 个布丁向左移动,那么我们就枚举上一个不动的布丁 \(j\),\(g_j+sum(a_j+1,a_j+i-j)\rightarrow f_i\),其中 \(sum(l,r)\) 表示 \([l,r]\) 中特殊格子的个数。
- 对于 \(g_i\),枚举上一个不动或向左移动的布丁 \(j\),那么显然布丁 \(j+1,j+2,\dots,i-1\) 都会向右移动直到靠到 \(i\) 上,即 \(f_j+sum(a_i-i+j+1,a_i)\rightarrow g_i\)。
当然也可以改写成以下形式:
- \(f_j+sum(a_i-i+j+1,a_i)\rightarrow g_i\)
- \(g_i+sum(a_i+1,a_i+j)\rightarrow f_{i+j}\)
- \(g_i\rightarrow f_i\)
这样暴力 \(dp\) 是平方的,显然会炸,不过注意到特殊格子数量很少,考虑以此为突破口优化 \(dp\) 转移。比方说拿转移方程 \(f_j+sum(a_i-i+j+1,a_i)\rightarrow g_i\) 举例,注意到 \(f_i\leq f_{i+1}\),而如果 \(a_i-i+j+1\) 不是特殊格子,那么显然 \(sum(a_i-i+j+1,a_i)=sum(a_i-i+j+2,a_i)\),故 \(f_j+sum(a_i-i+j+1,a_i)=f_j+sum(a_i-i+j+2,a_i)\le f_{j+1}+sum(a_i-i+j+2,a_i)\),也就是说我们必定会从 \(a_i-i+j+1\) 为特殊格子的 \(j\) 转移来,故考虑转而枚举特殊格子,这样转移的复杂度就可降到 \(\mathcal O(m)\) 了。
最后,上述转移方程忽略的“连续的布丁会粘在一起”这个条件,其实这也异常容易解决,考虑求出 \(L_i\) 表示布丁 \(i\) 所在的布丁块的左端点,\(R_i\) 表示布丁 \(i\) 所在的布丁块的右端点——这显然可以线性求出。然后直接从对应转移位置的左右端点转移而来即可。可能讲得不是特别清楚,具体见代码罢。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e5;
const int MAXM=2e3;
const int MAXPOS=2e5;
int n,m,a[MAXN+5],b[MAXM+5],sum[MAXPOS+5];
int l[MAXN+5],r[MAXN+5],f[MAXN+5],g[MAXN+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);sort(a+1,a+n+1);
for(int i=1;i<=m;i++) scanf("%d",&b[i]),sum[b[i]]++;sort(b+1,b+m+1);
for(int i=1;i<=MAXPOS;i++) sum[i]+=sum[i-1];
a[0]=-MAXPOS;a[n+1]=MAXPOS+MAXPOS;
for(int i=1;i<=n;i++) l[i]=(a[i-1]+1==a[i])?l[i-1]:i;
for(int i=n;i;i--) r[i]=(a[i+1]-1==a[i])?r[i+1]:i;
for(int i=1;i<=n;i++){
f[i]=max(f[i],f[i-1]+sum[a[i]]-sum[a[i]-1]);
g[i]=max(g[i],f[i-1]+sum[a[i]]-sum[a[i]-1]);
for(int j=1;j<=m&&b[j]<a[i];j++) if(a[i]-b[j]<i){
chkmax(g[i],f[l[i-a[i]+b[j]]-1]+sum[a[i]]-sum[b[j]-1]);
}
chkmax(f[i],g[i]);
for(int j=m;j&&b[j]>=a[i];j--) if(b[j]-a[i]<=n-i){
chkmax(f[r[i+b[j]-a[i]]],g[i]+sum[b[j]]-sum[a[i]]);
}
} printf("%d\n",f[n]);
return 0;
}
Codeforces 436D - Pudding Monsters(dp)的更多相关文章
- CodeForces526F:Pudding Monsters (分治)
In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...
- Codeforces Gym101341K:Competitions(DP)
http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...
- codeforces 711C Coloring Trees(DP)
题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...
- codeforces#1154F. Shovels Shop (dp)
题目链接: http://codeforces.com/contest/1154/problem/F 题意: 有$n$个物品,$m$条优惠 每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物 ...
- Codeforces 1051 D.Bicolorings(DP)
Codeforces 1051 D.Bicolorings 题意:一个2×n的方格纸,用黑白给格子涂色,要求分出k个连通块,求方案数. 思路:用0,1表示黑白,则第i列可以涂00,01,10,11,( ...
- Codeforces 1207C Gas Pipeline (dp)
题目链接:http://codeforces.com/problemset/problem/1207/C 题目大意是给一条道路修管道,相隔一个单位的管道有两个柱子支撑,管道柱子高度可以是1可以是2,道 ...
- Codeforces 704C - Black Widow(dp)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...
- Codeforces 682B New Skateboard(DP)
题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...
- Codeforces 543D Road Improvement(DP)
题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...
随机推荐
- 改善深层神经网络-week3编程题(Tensorflow 实现手势识别 )
TensorFlow Tutorial Initialize variables Start your own session Train algorithms Implement a Neural ...
- linux shell脚本中的开头#!/bin/bash的含义
对于linux上需要执行 的shell脚本,通常第一行的内容是 #!/bin/bash 当然有很多时候不规范的写法可以忽略掉这一句,执行起来好像也是ok,结果没什么不一样 .. 这只是因为在我们常用 ...
- 二叉树中和为某一值的路径 牛客网 程序员面试金典 C++ Python
二叉树中和为某一值的路径 牛客网 程序员面试金典 题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一 ...
- hdu 2190 重建希望小学(数学,递推)
题意: N*3的教室,有2种砖,2*2.1*1. 问铺设教室的方案有多少种.(要铺满) 思路: 画一下图可以很快发现递推公式 代码: int main(){ int a[35]; mem(a,0); ...
- Docker 添加--insecure-registry 私有镜像仓库
方法一 [root@k8s-master01]# vi /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --inse ...
- 面试官:能手写实现call、apply、bind吗?
1 call.apply.bind 用法及对比 1.1 Function.prototype 三者都是Function原型上的方法,所有函数都能调用它们 Function.prototype.call ...
- lvs 四层负载相关
都打开 /etc/sysctl.conf 中的 net.ip4.ip_forward=1.开启路由转发功能. 分发器 : eth0:192.168.1.66 (VIP) eth1:192.168.2. ...
- ELK集群之kafka(7)
原理待补充: kafka依赖于zookeeper集群. 都是基于java 由于源码安装jdk 未声明bin下java 在各自server配置文件中声明 JAVA_HOME=/usr/local/jdk ...
- bash: mysql: command not found(解决方法)
执行mysql -uroot -p ,出现如图问题 解决方法如下: 执行以上命令,系统默认会查找/usr/bin下的命令,若这个命令不在该目录下,就会找不到,我们需要做的就是映射一个链接到/usr/b ...
- SpringCloud升级之路2020.0.x版-30. FeignClient 实现重试
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 需要重试的场景 微服务系统中,会遇到在线发布,一般的发布更新策略是:启动一个新的,启动成功 ...