Codeforces 题目传送门 & 洛谷题目传送门

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)的更多相关文章

  1. CodeForces526F:Pudding Monsters (分治)

    In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...

  2. Codeforces Gym101341K:Competitions(DP)

    http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...

  3. codeforces 711C Coloring Trees(DP)

    题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...

  4. codeforces#1154F. Shovels Shop (dp)

    题目链接: http://codeforces.com/contest/1154/problem/F 题意: 有$n$个物品,$m$条优惠 每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物 ...

  5. Codeforces 1051 D.Bicolorings(DP)

    Codeforces 1051 D.Bicolorings 题意:一个2×n的方格纸,用黑白给格子涂色,要求分出k个连通块,求方案数. 思路:用0,1表示黑白,则第i列可以涂00,01,10,11,( ...

  6. Codeforces 1207C Gas Pipeline (dp)

    题目链接:http://codeforces.com/problemset/problem/1207/C 题目大意是给一条道路修管道,相隔一个单位的管道有两个柱子支撑,管道柱子高度可以是1可以是2,道 ...

  7. Codeforces 704C - Black Widow(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...

  8. Codeforces 682B New Skateboard(DP)

    题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...

  9. Codeforces 543D Road Improvement(DP)

    题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...

随机推荐

  1. 初始HTML03

    **------------恢复内容开始------------** HTML 页面标签组成 一个完整的页面仅有一个html元素,在这个元素之下,包含head和body元素,前者负责说明页面结构,后者 ...

  2. 5个步骤,教你瞬间明白线程和线程安全.md

    记得刚来杭州面试的时候,有一家公司的技术总监问了我这样一个问题:你来说说有哪些线程安全的类?我心里一想,这我早都背好了,稀里哗啦说了一大堆. 他又接着问:那你再来说说什么是线程安全?--然后我就GG了 ...

  3. 生产环境全链路压测平台 Takin

    什么是Takin? Takin是基于Java的开源系统,可以在无业务代码侵入的情况下,嵌入到各个应用程序节点,实现生产环境的全链路性能测试,适用于复杂的微服务架构系统. Takin核心原理图 Taki ...

  4. spring源码分析(二)- 容器基础

    1.基本用法 用过Spring的都知道,bean是Spring中最基础也是最核心的.首先看一个简单的例子. 一个类和一个配置文件 package bean; public class MyBean { ...

  5. 视频编码GOP

    GOP group of pictures GOP 指的就是两个I帧之间的间隔. 比较说GOP为120,如果是720 p60 的话,那就是2s一次I帧. 在视频编码序列中,主要有三种编码帧:I帧.P帧 ...

  6. hdu 3199 Hamming Problem(构造?枚举?)

    题意: For each three prime numbers p1, p2 and p3, let's define Hamming sequence Hi(p1, p2, p3), i=1, . ...

  7. JAVA笔记1__基本数据类型/输入输出/随机数/数组

    /**八种基本数据类型 boolean byte short int long char float double */ public class test1{ public static void ...

  8. 前端面试手写代码——模拟实现new运算符

    目录 1 new 运算符简介 2 new 究竟干了什么事 3 模拟实现 new 运算符 4 补充 预备知识: 了解原型和原型链 了解this绑定 1 new 运算符简介 MDN文档:new 运算符创建 ...

  9. oracle 定时任务增、删、改、查

    增: 创建一个计划任务 begin sys.dbms_job.submit(job=>:job, what=>'要定时执行的存储过程名:',--例如:包名.存储过程名;  记得写分号 ne ...

  10. CentOS 7 tmpwatch 2.11 版本变更,移除 cronjob 任务

    老版本(RHEL6) tmpwatch 原理 在 RHEL6 上,/tmp 目录的清理工作通常是交给 tmpwatch 程序来完成的,tmpwatch 的工作机制是通过 /etc/cron.daily ...