P6764 [APIO2020] 粉刷墙壁
思路:
本质上能进行的操作就是我们算出从第 \(i\) 块砖开始,连续刷 \(M\) 块砖,是否有承包商可以刷出期望颜色。
那么设 \(f_i\) 表示 \([i,i+m-1]\) 是否合法,那么就变成了最小区间覆盖问题。
最小区间覆盖问题
令 \(Max\) 表示当前覆盖了 \([1,Max]\)。
那么我们需要找到左端点在 \([1,Max+1]\) 内,且右端点最大的区间。
在本题中因为区间长度都为 \(m\),那么我们只需要找到尽可能在最后的合法 \(f_i\)。
此时 \(Max \gets i+m-1\),那么对于小于 \(j\) 的 \(i\),是无法覆盖到 \(i+m-1\) 之后的,于是就没有贡献了,于是我们可以直接走指针维护。
最小区间覆盖代码
ll get(){
ll Max=-1,x=0,id,ans=0;
while(Max<n-1){
id=-1;
while(x<=Max+1&&x<n){
if(f[x])
id=x;
x++;
}
if(id==-1)
return -1;
Max=id+m-1;
ans++;
}
return ans;
}
那么我们需要考虑的就是如何求出 \(f_i\)。
28pts:
对于每个 \(i\),暴力枚举一个 \(j\),然后查看是否能匹配上。
时间复杂度为 \(O(NM^2)\)。
51pts:
考虑动态规划优化,定义 \(dp_{i,j}\) 表示从第 \(i\) 块墙壁开始,从第 \(j\) 个商家开刷最多能刷几块墙。
那么若第 \(j\) 个商家不能刷第 \(i\) 个墙壁,则:
\]
否则能刷:
\]
注意,空间开不下,考虑滚动数组优化。
时间复杂度为 \(O(NM)\)。
震惊的是,这玩意儿竟然过了……
离大谱。
$O(NM)$ 代码
int minimumInstructions(int N, int M, int K,vector<int> C,vector<int> A,vector<vector<int>> B){
n=N,m=M,k=K;
for(int i=0;i<n;i++)
a[i]=C[i];
for(int i=0;i<m;i++){
len[i]=A[i];
for(auto v:B[i])
s[v].push_back(i);
}
for(int i=n-1;i>=0;i--){
for(int j=0;j<m;j++)
dp[i&1ll][j]=0;
for(auto j:s[a[i]]){
dp[i&1ll][j]=dp[(i&1ll)^1ll][(j+1)%m]+1;
if(dp[i&1ll][j]>=m)
f[i]=1;
}
}
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB"<<'\n';
return get();
}
100pts:
注意到可以优化上面状态转移的 \(j\)。
我们可以提前预处理能刷颜色 \(x\) 的承包商的集合 \(S_x\),那么 \(j \in S_{c_i}\)。
但是因为是滚动数组,实时清空的话复杂度又上去了,那么再维护一个时间戳即可。
时间复杂度为 \(O(\sum f(k))\)。
完整代码:
#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef int ll;
bool Begin;
const ll N=100100,M=50050;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
ll n,m,k;
ll a[N],len[M];
ll dp[2][M],low[2][M];
vector<ll> s[N];
bool f[N];
bool End;
ll get(){
ll Max=-1,x=0,id,ans=0;
while(Max<n-1){
id=-1;
while(x<=Max+1&&x<n){
if(f[x])
id=x;
x++;
}
if(id==-1)
return -1;
Max=id+m-1;
ans++;
}
return ans;
}
int minimumInstructions(int N, int M, int K,vector<int> C,vector<int> A,vector<vector<int>> B){
n=N,m=M,k=K;
for(int i=0;i<n;i++)
a[i]=C[i];
for(int i=0;i<m;i++){
len[i]=A[i];
for(auto v:B[i])
s[v].push_back(i);
}
for(int i=n-1;i>=0;i--){
for(auto j:s[a[i]]){
if(low[(i&1ll)^1ll][(j+1)%m]!=i+1)
dp[i&1ll][j]=1;
else
dp[i&1ll][j]=dp[(i&1ll)^1ll][(j+1)%m]+1;
low[i&1ll][j]=i;
if(dp[i&1ll][j]>=m)
f[i]=1;
}
}
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB"<<'\n';
return get();
}
P6764 [APIO2020] 粉刷墙壁的更多相关文章
- APIO2020 粉刷墙壁
考场想了 5.5 h,第一部分分死活打不出来,做到崩盘,现在重做,感觉自己就是一个sb,放学在地铁上一眼就会了.哎. 可以把一个要求看作一个长度为 \(m\) 的区间:\([l, l + m - 1] ...
- Codeforces Round #198 (Div. 2)
A.The Wall 题意:两个人粉刷墙壁,甲从粉刷标号为x,2x,3x...的小块乙粉刷标号为y,2y,3y...的小块问在某个区间内被重复粉刷的小块的个数. 分析:求出x和y的最小公倍数,然后做一 ...
- [SinGuLaRiTy] NOIP互测模拟赛
[SinGuLaRiTy-1045] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 源文件名 输入输出文件 时间限制 内存限制 淘气的cch ...
- 【资料总结】html开发小实例
目 录 第1章 1 HTML的基本标签 1 第2章 25 表格基础 25 第3章 53 表单和框架 53 第4章 77 CSS样式表 77 第5章 104 使用Dreamweaver制作网页 104 ...
- as well as
一.as well 用法: 1.as well常用作状语,作“又:也”解,相当于too或also,常位于句末,无须用逗号与句子分开.如: I am going to London and my sis ...
- 【日语】日语单词N3_N4_N5
日语单词N3_N4_N5 单 词 讲 解 あ行单词 ああ:0[副]那样.那种 例句:ああ言うことはしないほうがいい.那样的事情最好不做. 電車の窓からごみを棄てているああ言うことはしないほうがいい. ...
- 日语单词N3_N4_N5
单 词 讲 解 あ行单词 ああ:0[副]那样.那种 例句:ああ言うことはしないほうがいい.那样的事情最好不做. 電車の窓からごみを棄てているああ言うことはしないほうがいい. 挨拶(あいさつ):① 寒暄 ...
- java设计模式3——建造者模式
java设计模式3--建造者模式 1.建造者模式介绍: 建造者模式属于创建型模式,他提供了一种创建对象得最佳方式 定义: 将一个复杂对象的构建和与它的表示分离,使得同样的构建过程可以创建不同的表示 主 ...
- poj1821 Fence(dp,单调队列优化)
题意: 由k(1 <= K <= 100)个工人组成的团队应油漆围墙,其中包含N(1 <= N <= 16 000)个从左到右从1到N编号的木板.每个工人i(1 <= i ...
- [LeetCode] Paint Fence 粉刷篱笆
There is a fence with n posts, each post can be painted with one of the k colors. You have to paint ...
随机推荐
- OpenSearch 与 Elasticsearch:哪个开源搜索引擎适合您?
当谈论到搜索引擎产品时,Elasticsearch 和 OpenSearch 是两个备受关注的选择.它们都以其出色的功能和灵活性而闻名,但在一些方面存在一些差异.在本文中,我们将从功能和延展性.工具与 ...
- 如何基于Perl实现批量蛋白名转换为基因名?以做后续GO与KEGG分析
众所周知,在完成蛋白组学组间差异蛋白筛选后,往往要做GO与KEGG功能富集分析,这就需要我们首先将蛋白名转换为基因名,或者找出基因ID.将蛋白名转化为基因名可能涉及不同的转换工具或数据库,这里有几种常 ...
- 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的.而 Mybatis 在查询关联对象或关联集合 ...
- mysql 8.0 客户端
1.mysql 8.0 command line client 2.mysql workbench
- Docker中部署单机Redis详细教程
1.拉取Redis镜像 # 拉取redis镜像,不指定版本则默认是最新版本 docker pull redis 2.查看镜像 # 列出本地镜像 docker images 3.准备配置文件路径 # 创 ...
- 01-Python介绍、安装与入门
Python介绍 关于Python Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言. 解释型:Python将代码边解释边运行,而不是像C一样编译.类似解释型的语言还有JAVA. ...
- 防止unordered_map 被卡方法
codeforces 上看到的,mark 一下代码.原作者:neal,原链接:https://codeforces.com/blog/entry/62393 struct custom_hash { ...
- 在Ubuntu 18.04 安装 adb
Ubuntu下安装ADB 背景 电脑上的USB口有问题,不方便调试:发现用于开发的服务器就在工位旁边. 先拿过来用一下. Ubuntu:18.04 做法 安装adb 做法有很多种,列举下列2种. 下载 ...
- 中间件-Nginx
一.nginx反向代理 输入 http://xxx.com/plat/login 跳转: http://localhost:8383/plat/login 将某个指定的域名代理到指定的服务 http: ...
- 在Mac上使用Emacs初步
其他操作系统估计也差不多. 安装 如果使用brew就是brew install emacs.安装后不会在Applications里面显示一个程序,需要在命令行里执行emacs. 使用 进入和退出 上面 ...