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. 性能利器 Takin 来了!首个生产环境全链路压测平台正式开源

    6 月 25 日,国内知名的系统高可用专家数列科技宣布开源旗下核心产品能力,对外开放生产全链路压测平台产品的源代码,并正式命名为 Takin. 目前中国人寿.顺丰科技.希音.中通快递.中国移动.永辉超 ...

  2. Java字符串转数字和数字转字符串

    int转String有3种方式 (1)num + "" (2)String.valueOf(num) (3)Integer.toString(num) String转int有2种方 ...

  3. Coursera Deep Learning笔记 改善深层神经网络:超参数调试 Batch归一化 Softmax

    摘抄:https://xienaoban.github.io/posts/2106.html 1. 调试(Tuning) 超参数 取值 #学习速率:\(\alpha\) Momentum:\(\bet ...

  4. Java:Set接口小记

    Java:Set接口小记 对 Java 中的 Set接口 与 其实现类,做一个微不足道的小小小小记 概述 public interface Set<E> extends Collectio ...

  5. [no code][scrum meeting] Alpha 8

    项目 内容 会议时间 2020-04-14 会议主题 API文档第一版交付 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ). ...

  6. 【二食堂】Beta - Scrum Meeting 3

    Scrum Meeting 3 例会时间:5.15 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 继续完成文本区域划词添加的功能 issue 1. 划词功能已经实现,继续开发 ...

  7. 六个好习惯让你的PCB设计更优(转)

    PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...

  8. Less3

    继续第三关的学习 1.根据第一关的记录,我们判断出是什么注入 id=1' and '1'='1 id=1' and '1'='2 返回不同,所以存在字符型的注入 2. 这时候我们再用正常的报错猜解准备 ...

  9. 最接近的数 牛客网 程序员面试金典 C++ Python

    最接近的数 牛客网 程序员面试金典 C++ Python 题目描述 有一个正整数,请找出其二进制表示中1的个数相同.且大小最接近的那两个数.(一个略大,一个略小) 给定正整数int x,请返回一个ve ...

  10. hdu 5185 Equation(分析+DP)

    题意: Gorwin is very interested in equations. Nowadays she gets an equation like thisx1+x2+x3+⋯+xn=n, ...