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 ...
随机推荐
- Qt5.8.0编译QtMqtt库并使用该库连接有人云的例子
一 编译QtMqtt库Qt5.10才官方支持MQTT,但我用的Qt版本是5.8.0 Mingw_32BIT, 为了在Qt5.8.0上添加MQTT支持,需要自己编译源码 步骤: (1) git clon ...
- centos7 修改时区,同步时间,Mysql修改时区
查看时区 timedatectl status [root@localhost nova-back]# timedatectl status Local time: Thu 2019-05-23 15 ...
- php操作 cookie
1,设置cookie <?php setcookie('key'); setcookie('key1','value1'); setcookie(***); setcookie('key4', ...
- export CommonJS AMD ES6
export https://www.cnblogs.com/fayin/p/6831071.html 导入文件: a - b - c ,对象隔代消失,可转成函数返回 导入模块对象(命名) ...
- asp.net中的比较完美的验证码
要实现如图的效果的验证码,分以下步骤: 第一.布局好调用验证码的登录页面(命名:Login.aspx),注意:验证码位置可以是服务器控件 Image,也可以是html标签写的<img>,但 ...
- delphi FMX APP程序图标,闪屏,程序名
- ubuntu16.04 安装go
1.sudo add-apt-repository ppa:gophers/go 2.apt-get update 3.apt-get install golang 完成
- python函数:匿名函数、函数递归与二分法、面向过程编程
今天主要讲三大部分内容: 一.匿名函数二.函数递归与二分法三.面向过程编程 一.匿名函数: """ 1. 什么时匿名函数 def定义的是有名函数:特点是可以通过名字重复调 ...
- 1.java多线程_实现线程的两种方式
1.java多线程基本知识 1.1.进程介绍 不管是我们开发的应用程序,还是我们运行的其他的应用程序,都需要先把程序安装在本地的硬盘上.然后找到这个程序的启动文件, 启动程序的时候,其实是电脑把当前的 ...
- Linux useradd userdel groupadd groupdel gpasswd(组成员管理) id groups
添加用户 useradd [选项] 用户名 -u :指定UID标记号 -d:指定宿主目录,缺省为/home/用户名 -g:指定所属的基本组(组名或GID) -G: 指定所属的附加组(组名或GID) - ...