题解:AT_abc346_e [ABC346E] Paint
思路
定义矩阵为
显然不能在线处理,否则
考虑每一次操作所可以覆盖的格子,离线处理。
不同的列和列是互不干扰的,行同理。
行和列是干扰的,因为覆盖的是整行整列,所以它们一定互相干扰对方。如果第
如果有一行被覆盖了多次,我们只需要看最后一次。
我们造一组样例:
3 4 5
1 3 2
2 3 1
2 4 3
1 3 4
2 2 3
变化顺序将如下图所示:
如果我们倒序考虑最终结果图,那么会发现:
- 第
次操作因为是最后一次,所以每一个格子都能覆盖上。 - 第
次操作虽然不是最后一次,但是后面并没有列来干扰它了,所以也是每一个格子都能覆盖上。 - 第
次操作操作的是列,但是它后面已经有两行被提前覆盖了,所以它只能覆盖 格。 - 第
次同理。 - 第
次操作覆盖的第 行第 次操作已经覆盖过了,一个都不能覆盖。
这就是最终的结果图。
那么,最后会留下一些为
有两种方法。
- 数学法:
的数量就是全部的数量 被覆盖的数量。具体来说,如果 行 列被覆盖,则剩余 数量应为 。 - 暴力法。我们可以看成开局的全是
是进行了 次操作,每一次都覆盖成 造成的,这样增加了 的时间复杂度,但是仍然可以通过。
代码实现
显然我们可以记录数组表示操作,不过我这里用了一个栈。
栈满足后进先出的原则,调试更加方便。
还有答案数组要开
Code(暴力法):
#include<bits/stdc++.h>
using namespace std;
int h,l,m,opt,x,y;
long long ans[200005];
bool f[200005][3];
stack<int>st1;
stack<int>st2;
stack<int>st3;
int main(){
cin>>h>>l>>m;
for(int i=1;i<=h;i++){
st1.push(1);
st2.push(i);
st3.push(0);
}
for(int i=1;i<=l;i++){
st1.push(2);
st2.push(i);
st3.push(0);
}
while(m--){
cin>>opt>>x>>y;
st1.push(opt);
st2.push(x);
st3.push(y);
}
int hang=0,lie=0;
while(!st1.empty()){
opt=st1.top();
x=st2.top();
y=st3.top();
st1.pop();st2.pop();st3.pop();
if(f[x][opt]==1)continue;
f[x][opt]=1;
if(opt==1){
ans[y]+=(l-lie);
hang++;
}
else{
ans[y]+=(h-hang);
lie++;
}
}
int sum=0;
for(int i=0;i<=200000;i++){
if(ans[i]>0)sum++;
}
cout<<sum<<endl;
for(int i=0;i<=200000;i++){
if(ans[i]>0)cout<<i<<' '<<ans[i]<<endl;
}
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】