P9583 涂色 题解

P9583 涂色 题解

解法

题中说求最终有多少个方格涂着颜色,那我们可以求有多少个方格没有颜色,用方格的总数减去没有颜色的方格数即为所求。

考虑本题涂色规律,涂上 kkk 层颜料的方格其颜料会被擦去,这种操作的本质是对 kkk 取模,所以没有颜色的方格即该方格所在的行、列被涂色的次数和可以被 kkk 整除。

现在分别统计每个行、每个列的涂色次数,然后对行、列分别开两个桶,维护每行、每列的涂色次数对 kkk 取模后的值。

然后枚举桶里的元素。设有 rubhirubh_irubhi 个行的涂色次数对 kkk 取模等于 iiirublirubl_irubli 个列的涂色次数对 kkk 取模等于 iii,则想要让一个方格没有颜色,则必须满足 hangi+liei≡0(modk)hang_i + lie_i \equiv 0 \pmod{k}hangi+liei0(modk),所以对于 rubhirubh_irubhi 个行,只有 rublk−irubl_{k-i}rublki 个列与之匹配才能是没有颜色的方格,根据乘法原理,有 rubhi×rublk−irubh_i \times rubl_{k-i}rubhi×rublki 个方格没有颜色。特殊地,rubh0rubh_0rubh0rubl0rubl_0rubl0 匹配。

求解公式即为 rubh0×rubl0+∑i=1i<krubhi×rublk−irubh_0 \times rubl_0 + \sum \limits _{i=1} ^{i < k} rubh_i \times rubl_{k-i}rubh0×rubl0+i=1i<krubhi×rublki,时间复杂度 O(q+k)\mathcal{O}(q + k)O(q+k)

代码

#include<bits/stdc++.h>
using namespace std;
namespace fast_IO
{
	/*
	快读快写
	*/
};
using namespace fast_IO;
int n,m,q,k,hang[200010],lie[200010],rubh[500010],rubl[500010];
inline void delh(int x)
{
	if(x==k-1) rubh[x]--,rubh[0]++;
	else rubh[x]--,rubh[x+1]++;
}
inline void dell(int x)
{
	if(x==k-1) rubl[x]--,rubl[0]++;
	else rubl[x]--,rubl[x+1]++;
}
long long ans;
int main()
{
	read(n),read(m),read(q),read(k),rubh[0]=n,rubl[0]=m;
	for(int i=1,op,x;i<=q;i++)
	{
		read(op),read(x);
		if(op==1) hang[x]++,delh((hang[x]-1)%k);
		else lie[x]++,dell((lie[x]-1)%k);
	}
	ans+=1ll*rubh[0]*rubl[0];
	for(int i=1;i<k;i++) ans+=1ll*rubh[i]*rubl[k-i];
	cout<<1ll*n*m-ans;
	return 0;
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值