思路:

本质上能进行的操作就是我们算出从第 \(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\) 个墙壁,则:

\[dp_{i,j}=0
\]

否则能刷:

\[dp_{i,j} = dp_{i+1,(j+1) \bmod M} + 1
\]

注意,空间开不下,考虑滚动数组优化。

时间复杂度为 \(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] 粉刷墙壁的更多相关文章

  1. APIO2020 粉刷墙壁

    考场想了 5.5 h,第一部分分死活打不出来,做到崩盘,现在重做,感觉自己就是一个sb,放学在地铁上一眼就会了.哎. 可以把一个要求看作一个长度为 \(m\) 的区间:\([l, l + m - 1] ...

  2. Codeforces Round #198 (Div. 2)

    A.The Wall 题意:两个人粉刷墙壁,甲从粉刷标号为x,2x,3x...的小块乙粉刷标号为y,2y,3y...的小块问在某个区间内被重复粉刷的小块的个数. 分析:求出x和y的最小公倍数,然后做一 ...

  3. [SinGuLaRiTy] NOIP互测模拟赛

    [SinGuLaRiTy-1045] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 源文件名 输入输出文件 时间限制 内存限制 淘气的cch ...

  4. 【资料总结】html开发小实例

    目 录 第1章 1 HTML的基本标签 1 第2章 25 表格基础 25 第3章 53 表单和框架 53 第4章 77 CSS样式表 77 第5章 104 使用Dreamweaver制作网页 104 ...

  5. as well as

    一.as well 用法: 1.as well常用作状语,作“又:也”解,相当于too或also,常位于句末,无须用逗号与句子分开.如: I am going to London and my sis ...

  6. 【日语】日语单词N3_N4_N5

    日语单词N3_N4_N5 单 词 讲 解 あ行单词 ああ:0[副]那样.那种 例句:ああ言うことはしないほうがいい.那样的事情最好不做. 電車の窓からごみを棄てているああ言うことはしないほうがいい. ...

  7. 日语单词N3_N4_N5

    单 词 讲 解 あ行单词 ああ:0[副]那样.那种 例句:ああ言うことはしないほうがいい.那样的事情最好不做. 電車の窓からごみを棄てているああ言うことはしないほうがいい. 挨拶(あいさつ):① 寒暄 ...

  8. java设计模式3——建造者模式

    java设计模式3--建造者模式 1.建造者模式介绍: 建造者模式属于创建型模式,他提供了一种创建对象得最佳方式 定义: 将一个复杂对象的构建和与它的表示分离,使得同样的构建过程可以创建不同的表示 主 ...

  9. poj1821 Fence(dp,单调队列优化)

    题意: 由k(1 <= K <= 100)个工人组成的团队应油漆围墙,其中包含N(1 <= N <= 16 000)个从左到右从1到N编号的木板.每个工人i(1 <= i ...

  10. [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 ...

随机推荐

  1. Win11系统下的MindSpore环境搭建

    技术背景 笔者尝试过不少编程环境搭建的方案,例如常见的Ubuntu.Deepin.CentOS,也用过很多人力荐的Manjaro,这些发行版在需要办公的条件下,一般都需要结合Windows双系统使用. ...

  2. NET9 提供HybridCache解决分布式缓存中存在的远程链接&序列化带来的性能问题

    下面是一个标准的IDistributedCache用例: public class SomeService(IDistributedCache cache) { public async Task&l ...

  3. docker容器单机编排

    随着网站架构的升级,容器也使用的越发频繁,应用服务和容器间的关系也越发复杂. 这就要求研发人员能够更好的方法去管理数量较多的容器服务,而不能手动的去挨个管理. 例如一个LNMP的架构,就得部署web服 ...

  4. 博客正式更换为emlog

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 博客正式更换为emlog 日期:2017-4-2 阿珏 谈 ...

  5. Jenkins构建项目遇到的问题总结

    4.2.1  在Windows下,Jenkins运行python项目 https://www.jianshu.com/p/f6edbaaa8a0d 4.2.2  配置不同类型的项目的操作步骤 http ...

  6. 面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?

    一.写在开头 在上一篇学习序列化的文章中我们提出了这样的一个问题: "如果在我的对象中,有些变量并不想被序列化应该怎么办呢?" 当时给的回答是:不想被序列化的变量我们可以使用tra ...

  7. Freertos学习:07-队列

    --- title: rtos-freertos-07-队列 EntryName : rtos-freertos-07 date: 2020-06-23 09:43:28 categories: ta ...

  8. 【Kafka最佳实践】合理安排kafka的broker、partition、consumer数量

    broker的数量最好大于等于partition数量 一个partition最好对应一个硬盘,这样能最大限度发挥顺序写的优势. 一个broker如果对应多个partition,需要随机分发,顺序IO会 ...

  9. 【论文阅读】自动驾驶光流任务 DeFlow: Decoder of Scene Flow Network in Autonomous Driving

    再一次轮到讲自己的paper!耶,宣传一下自己的工作,顺便完成中文博客的解读 方便大家讨论. Title Picture Reference and pictures paper: https://a ...

  10. 2.3T NPU强势登场!NXP i.MX 8M Plus开启工业新篇章,14纳米!

                    更多产品详情以及购买咨询 可添加如下客服人员微信 (即刻添加,马上咨询) 更多i.MX 8M Plus产品资料 可长按二维码识别下载 如需选购,请登录创龙科技天猫旗舰店 ...