noi.ac #529 神树的矩阵
题目链接:戳我
当 \(max(n, m) \ge 3\) 时,可以如下构造:
考虑下面这样三个矩阵,红 + 蓝 − 绿得到的矩阵是一个第一行和最后一行全是 1,其他地方全是 0 的矩阵。
那么如果需要把中间某个位置变成 1,可以在红或蓝矩阵中的对应位置加一个 1。
如果需要把第一行或最后一行某个位置变成 0,可以在绿矩阵中的对应位置加一个 1。


然后对于其他情况分别特判就行了(具体哪些可以看main函数)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define MAXN 510
#define mp make_pair
using namespace std;
int n,m;
int move_x[4]={0,0,1,-1},move_y[4]={1,-1,0,0};
char s[MAXN][MAXN];
namespace subtask_0
{
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1')
return false;
return true;
}
}
namespace subtask_1
{
int done[MAXN][MAXN];
inline bool bfs(int x,int y)//不带done的清空操作
{
queue<pair<int,int> >q;
q.push(mp(x,y));
while(!q.empty())
{
int u_x=q.front().first;
int u_y=q.front().second;
q.pop();
done[u_x][u_y]=1;
for(int k=0;k<=3;k++)
{
int xx=u_x+move_x[k];
int yy=u_y+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0'||done[xx][yy]) continue;
done[xx][yy]=1;
q.push(mp(xx,yy));
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1'&&done[i][j]==0) return false;
return true;
}
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1')
{
if(bfs(i,j)==true) return true;
else return false;
}
}
inline void solve()
{
printf("1\n+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",s[i][j]);
puts("");
}
}
}
namespace subtask_2
{
int cnt,cur_ans,pos;
int fa[MAXN*MAXN],id[MAXN][MAXN];
map<int,int>ex;
set<int>sset[MAXN*MAXN];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
id[i][j]=++cnt,fa[cnt]=cnt;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<=3;k++)
{
int xx=i+move_x[k];
int yy=j+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[i][j]!=s[xx][yy]) continue;
int t=find(id[i][j]),tt=find(id[xx][yy]);
if(t!=tt) fa[t]=tt;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0') continue;
int t=find(id[i][j]);
if(!ex.count(t)) ex[t]=1,cur_ans++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0')
for(int k=0;k<=3;k++)
{
int xx=i+move_x[k];
int yy=j+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0') continue;
int t=find(id[i][j]),tt=find(id[xx][yy]);
sset[t].insert(tt);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(s[i][j]=='0')
{
int t=find(id[i][j]);
if((int)sset[t].size()==cur_ans)
{
pos=t;
break;
}
}
if(pos!=0) break;
}
if(pos==0) return false;
return true;
}
inline void solve()
{
printf("2\n+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='1'||(s[i][j]=='0'&&find(id[i][j])==pos)) printf("1");
else printf("0");
}
puts("");
}
printf("-\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0'&&find(id[i][j])==pos) printf("1");
else printf("0");
}
puts("");
}
}
}
inline void solve_n_1()
{
vector<pair<int,int> >vec;
int now=1;
while(now<=m)
{
int cnt1,cnt2;
while(now<=m&&s[1][now]=='0') now++;
if(now<=m&&s[1][now]=='1')
{
cnt1=now;
while(now<=m&&s[1][now]=='1') now++;
cnt2=now-1;
vec.push_back(mp(cnt1,cnt2));
}
}
printf("%d\n",(int)vec.size());
for(int i=0;i<vec.size();i++)
{
printf("+\n");
for(int j=1;j<=m;j++)
{
if(vec[i].first<=j&&j<=vec[i].second) printf("1");
else printf("0");
}
puts("");
}
}
inline void solve_m_1()
{
vector<pair<int,int> >vec;
int now=1;
while(now<=n)
{
int cnt1,cnt2;
while(now<=n&&s[now][1]=='0') now++;
if(now<=n&&s[now][1]=='1')
{
cnt1=now;
while(now<=n&&s[now][1]=='1') now++;
cnt2=now-1;
vec.push_back(mp(cnt1,cnt2));
// printf("[%d %d]\n",cnt1,cnt2);
}
}
printf("%d\n",(int)vec.size());
for(int i=0;i<vec.size();i++)
{
printf("+\n");
for(int j=1;j<=n;j++)
{
if(vec[i].first<=j&&j<=vec[i].second) printf("1\n");
else printf("0\n");
}
// puts("");
}
}
namespace others
{
char t[MAXN][MAXN],r[MAXN][MAXN],q[MAXN][MAXN];
inline void print()
{
printf("3\n");
printf("+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",t[i][j]);
puts("");
}
printf("+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",r[i][j]);
puts("");
}
printf("-\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",q[i][j]);
puts("");
}
}
inline void solve_m_2()
{
for(int i=1;i<=n;i++)
{
t[i][1]='1';
t[i][2]=(s[i][2]=='1'?'1':'0');
}
for(int i=1;i<=n;i++)
{
r[i][2]='1';
r[i][1]=(s[i][1]=='1'?'1':'0');
}
for(int i=1;i<=n;i++) q[i][1]=q[i][2]='1';
print();
}
inline void solve()
{
for(int i=1;i<=n;i++)
{
t[i][1]='1',t[i][m]='0';
r[i][1]='0',r[i][m]='1';
for(int j=2;j<m;j++) t[i][j]=r[i][j]=s[i][j];
if(i&1)
for(int j=1;j<m;j++) t[i][j]='1';
else
for(int j=2;j<=m;j++) r[i][j]='1';
}
for(int i=1;i<=n;i++)
{
q[i][1]=(s[i][1]=='0'?'1':'0');
q[i][m]=(s[i][m]=='0'?'1':'0');
for(int j=2;j<m;j++) q[i][j]='1';
}
print();
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
// freopen("ce.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
if(subtask_0::check()) printf("0\n");
else if(subtask_1::check()) subtask_1::solve();
else if(subtask_2::check()) subtask_2::solve();
else if(n==1) solve_n_1();
else if(m==1) solve_m_1();
else if(m==2) others::solve_m_2();
else others::solve();
return 0;
}
noi.ac #529 神树的矩阵的更多相关文章
- noi.ac #531 神树和物品
题目链接:戳我 决策单调性 (蒟蒻终于会写决策单调性啦!考试全场切这题就我不会啊嘤) (证明?不会啊,自己打表看QAQ) 44pts \(O(n^2)\)代码: #include<iostrea ...
- noi.ac #528 神树和排列
题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorith ...
- noi.ac #525 神树的权值
mcfx神仙的题qwq 题目链接:戳我 首先,我们知道30%的分还是挺好做的 直接枚举根,然后dfs一遍以\(O(n)\)的时间复杂度求出来有多少神仙点 代码如下: #include<iostr ...
- NOI.AC NOIP模拟赛 第三场 补记
NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...
- # NOI.AC省选赛 第五场T1 子集,与&最大值
NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...
- NOI.ac #31 MST DP、哈希
题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...
- NOI.AC NOIP模拟赛 第五场 游记
NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...
- NOI.AC NOIP模拟赛 第六场 游记
NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...
- NOI.AC NOIP模拟赛 第二场 补记
NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...
随机推荐
- mysql在B-Tree上创建伪哈希索引
构建哈希的过程 select过程 长字符串下,构建索引可通过自定义哈希作为索引,本人通过实验,在3百多个数据记录的下,性能效果很明显,完全不是一个等级.以下为索引前后几种情况对比 无索引的url:直接 ...
- Spring 容器中 Bean 的生命周期
Spring 容器中 Bean 的生命周期 1. init-method 和 destory-method 方法 Spring 初始化 bean 或销毁 bean 时,有时需要作一些处理工作,因此 s ...
- 异常-try...catch的方式处理异常2
package cn.itcast_02; /* * A:一个异常 * B:二个异常的处理 * a:每一个写一个try...catch * b:写一个try,多个catch * try{ * ... ...
- .NET中跨线程访问winform控件的方法
1 第一种方式 MethodInvoker invoker = () => { richTextBox1.AppendText(_ClientSocketModelConnectedEvent. ...
- 转载: Linux查看系统开机时间
转自: https://www.cnblogs.com/kerrycode/p/3759395.html 查看Linux系统运行了多久时间,此时需要知道上次开机启动时间: 有时候由于断电或供电故障突然 ...
- Python实现串口通信(pyserial)
pyserial模块封装了对串口的访问,兼容各种平台. 安装 pip insatll pyserial 初始化 简单初始化示例 import serial ser = serial.Serial('c ...
- 使用PyQt5自制文件查找工具,并生成EXE文件
一.工作中,有一个关键词查找工作,查找开发版本中使用的文本,有哪些词语是非法的,一个一个去查太累了,所以想到了用代码来实现.可后来想想,能否做成简单的小工具,大家都可以使用. 于是就着手编写工具.原来 ...
- JAVA语言程序设计课后习题----第三单元解析(仅供参考)
1 本题水题,记住要知道输入格式即可 import java.util.Scanner; public class test { public static void main(String[] ar ...
- springboot项目logback.xml或者logback-spring.xml中读取不到application.yml或application.properties配置文件中的配置解决办法
在springboot项目中我们可能想要实现不同环境的日志项目配置不同,比如我想让不同环境的日志路径不同. 这时候我们很容易想: 1.到将日志路径配置在springboot的:application- ...
- 网桥 交换机 VLAN 等基本概念---以太网
交换机: 集线器: 基带信号:基带信号就是幅度只有两种离散值的数字信号. 基带传输:用基带信号实现数据传输的方式. 曼彻斯特编码 帧对界和MAC帧 后退算法 和 捕获效应 冲突域 最短帧长 网桥 网桥 ...