【2020五校联考NOIP #8】自闭
题目传送门
题意:
有一个 \(n \times m\) 的矩阵,里面已经填好了 \(k\) 个非负整数。
问是否能在其它 \(n \times m-k\) 个格子里各填上一个非负整数,使得得到的矩阵满足以下条件:
- 在任意一个 \(2 \times 2\) 的子矩阵中,左上角的数 \(+\) 右下角的数 \(=\) 右上角的数 \(+\) 左下角的数。
如果可以输出 Zibi
否则输出 Zikai
。
\(n,m,k \in [1,10^5]\)
考虑探究这个矩阵有什么性质。假设有一个 \(3 \times 3\) 的子矩阵:
\]
根据上面的条件我们有:
\]
由第一个和第三个式子可以得到 \(a+f=g+c\)
由第二个和第四个式子可以得到 \(d+i=g+f\)
再把这两个式子相结合一下可以得到 \(a+i=c+d\)
于是我们初步得到一个结论:如果有个满足条件的矩阵 \(A\),那么对于任意 \(x_1,x_2 \in [1,n],y_1,y_2 \in [1,m],x_1 \neq x_2,y_1 \neq y_2\),都有
\]
根据这个性质,考虑固定住第一行和第一列,根据上面的性质填好剩下 \((n-1)\times(m-1)\) 个数。
那么显然有 \(A_{i,j}=A_{1,j}+A_{i,1}-A_{1,1}\)
我们令 \(r_1=0,r_i(i>2)=A_{i,1}-A_{1,1}\)。
再令 \(c_i=A_{1,i}\)。
那么对于任意 \(i \in [1,n],j \in [1,m]\),你把 \(r_i+c_j\) 计算出来就会得到 \(A_{i,j}=r_i+c_j\)
现在我们的目标是找出是否存在满足条件的 \(r_i,c_i\)
我们假设同一行中有两个已经填好的数 \(A_{i,y_1}=v_1,A_{i,y_2}=v_2\)。
那么 \(v_1=r_i+c_{y_1},v_2=r_i+c_{y_2}\)。
两式相减可以得到 \(c_{y_1}-c_{y_2}=v_1-v_2\)。
在顶点 \(y_1,y_2\) 之间连一条有向边边,边权为 \(v_1-v_2\)。
这样建边看似是 \(n^2\) 的,不过注意到如果已知 \(c_{y_1}-c_{y_2}=v_1-v_2,c_{y_1}-c_{y_3}=v_1-v_3\),就可以直接得出 \(c_{y_2}-c_{y_3}=v_2-v_3\),所以可以把第 \(i\) 行填好数的位置按列数从小到大排序,只用在相邻顶点之间建边,这样边数最多是 \(\mathcal O(n)\) 的。
然后你对于每个连通块进行一遍 \(dfs\),求出该连通块中编号最小的点 \(x\) 到每个点 \(i\) 的距离 \(dist_i\),那么真正的 \(c_i=c_x+dist_i\)。
然后你对于每条边 \((u,v,w)\) 都检查 \(dist_v\) 是否与 \(dist_u+w\) 相等就行了。
由于我们每次连边都是从编号小的点连向编号大的点的,所以把每个连通块中编号最小的点作为基准是没问题的。
等等我们好像忽略了一个条件。
题目中要求填上一个非负整数,而我们只检验了是否可以填整数,而忽视了非负这个条件。
怎样解决呢?
对于每一行,假设有一个位置 \(j\) 填上了数 \(v\),\(j\) 所在列的连通块中编号最小的点为 \(x\)。
那么 \(r_i+c_j=v\),即 \(r_i+c_x+dist_j=v\)
于是我们得到 \(r_i+c_x=v-dist_j\)。
再假设该连通块中 \(dist_k\) 最小的点 \(z\)。
那么 \(A_{i,z}=r_i+c_z=r_i+c_x+dist_z\)。
如果 \(r_i+c_x+dist_z<0\) 就说明 \(A_{i,z}<0\),不合法。
于是这题就做完了。
/*
Contest: -
Problem: NFLSOJ 713
Author: tzc_wk
Time: 2020.10.20
*/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define y1 y1010101010101
#define y0 y0101010101010
typedef pair<int,int> pii;
typedef long long ll;
int n,m,k;
struct data{
int x,y,z;
} a[200005];
bool cmpx(data x,data y){
return x.x<y.x;
}
bool cmpy(data x,data y){
return x.y<y.y;
}
struct edge{
int u,v,w;
} edr[200005],edc[200005];
int ecntr=0,ecntc=0;
vector<pii> gr[200005],gc[200005];
vector<data> dr[200005],dc[200005];
int disr[200005],disc[200005];
inline void adder(int u,int v,int w){
edr[++ecntr]={u,v,w};
gr[u].pb(make_pair(v,w));
}
inline void addec(int u,int v,int w){
edc[++ecntc]={u,v,w};
gc[u].pb(make_pair(v,w));
}
bool visr[200005],visc[200005];
int compr=0,compc=0;
int fromr[200005],fromc[200005];
inline void dfsr(int x){
if(visr[x]) return;
visr[x]=1;fromr[x]=compr;
for(int i=0;i<gr[x].size();i++){
int y=gr[x][i].fi,z=gr[x][i].se;
disr[y]=disr[x]+z;dfsr(y);
}
}
inline void dfsc(int x){
if(visc[x]) return;
visc[x]=1;fromc[x]=compc;
for(int i=0;i<gc[x].size();i++){
int y=gc[x][i].fi,z=gc[x][i].se;
disc[y]=disc[x]+z;dfsc(y);
}
}
int mnr[200005],mnc[200005];
int main(){
// freopen("C:\\Users\\汤\\Downloads\\problem_714\\subtask2\\zibi3.in","r",stdin);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++){
data in;scanf("%d%d%d",&in.x,&in.y,&in.z);
dr[in.x].push_back(in);dc[in.y].push_back(in);a[i]=in;
}
for(int i=1;i<=n;i++) sort(all(dr[i]),cmpy);
for(int i=1;i<=m;i++) sort(all(dc[i]),cmpx);
for(int i=1;i<=n;i++){
if(dr[i].empty()) continue;
for(int j=1;j<dr[i].size();j++){
addec(dr[i][j-1].y,dr[i][j].y,dr[i][j].z-dr[i][j-1].z);
addec(dr[i][j].y,dr[i][j-1].y,dr[i][j-1].z-dr[i][j].z);
}
}
for(int i=1;i<=m;i++){
if((dc[i].empty())) continue;
for(int j=1;j<dc[i].size();j++){
adder(dc[i][j-1].x,dc[i][j].x,dc[i][j].z-dc[i][j-1].z);
adder(dc[i][j].x,dc[i][j-1].x,dc[i][j-1].z-dc[i][j].z);
}
}
for(int i=1;i<=n;i++) if(!visr[i]) compr++,dfsr(i);
for(int i=1;i<=m;i++) if(!visc[i]) compc++,dfsc(i);
for(int i=1;i<=ecntr;i++){
if(disr[edr[i].v]!=disr[edr[i].u]+edr[i].w)
return puts("Zikai"),0;
}
for(int i=1;i<=ecntc;i++){
if(disc[edc[i].v]!=disc[edc[i].u]+edc[i].w)
return puts("Zikai"),0;
}
for(int i=1;i<=compr;i++) mnr[i]=0x3f3f3f3f;
for(int i=1;i<=compc;i++) mnc[i]=0x3f3f3f3f;
// puts("A");
for(int i=1;i<=n;i++) mnr[fromr[i]]=min(mnr[fromr[i]],disr[i]);
for(int i=1;i<=m;i++) mnc[fromc[i]]=min(mnc[fromc[i]],disc[i]);
for(int i=1;i<=n;i++){
int mn=0x3f3f3f3f;
for(int j=0;j<dr[i].size();j++){
int x=dr[i][j].y;
mn=min(mn,dr[i][j].z-disc[x]+mnc[fromc[x]]);
// printf("%d %d %d\n",i,x,dr[i][j].z-disc[x]+mnc[fromc[x]]);
}
// printf("%d %d\n",i,mn);
if(mn<0) return puts("Zikai"),0;
}
puts("Zibi");
return 0;
}
【2020五校联考NOIP #8】自闭的更多相关文章
- 【2020五校联考NOIP #6】三格缩进
题意: 给出 \(n\) 个数 \(a_1,a_2,\dots,a_n\),你要进行 \(m\) 次操作,每次操作有两种类型: \(1\ p\ x\):将 \(a_p\) 改为 \(x\). \(2\ ...
- 【2020五校联考NOIP #8】狗
题面传送门 原题题号:Codeforces 883D 题意: 有 \(n\) 个位置,每个位置上要么有一条狗,要么有一根骨头,要么啥都没有. 现在你要给每个狗指定一个方向(朝左或朝右). 朝左的狗可以 ...
- 【2020五校联考NOIP #7】道路扩建
题面传送门 题意: 给出一张 \(n\) 个点 \(m\) 条边的无向图 \(G\),第 \(i\) 条边连接 \(u_i,v_i\) 两个点,权值为 \(w_i\). 你可以进行以下操作一次: 选择 ...
- 【2020五校联考NOIP #4】今天的你依旧闪耀
题面传送门 题意: 对于一个长度为 \(n\)(\(n\) 为偶数)的排列 \(p\),定义一次"变换"后得到的排列 \(p'\) 为: \(p'_i=\begin{cases}p ...
- 【2020五校联考NOIP #3】序列
题面传送门 原题题号:Codeforces Gym 101821B 题意: 给出一个排列 \(p\),要你找出一个最长上升子序列(LIS)和一个最长下降子序列(LDS),满足它们没有公共元素.或告知无 ...
- 【2020五校联考NOIP #7】伟大的卫国战争
题面传送门 题意: 数轴上有 \(n\) 个点,现在要在它们之间连 \(m\) 条边,第 \(i\) 条边连接 \(a_i,b_i\) 两个点. 现在你要钦定每条边连在数轴的上方还是下方,使得任意两条 ...
- 【2020五校联考NOIP #6】最佳观影
题意: 给出一个 \(k \times k\) 的网格和 \(n\) 次操作.其中 \(k\) 为奇数. 每次操作给出一个数 \(m\).每次你要找出一个三元组 \((x,l,r)\) 使得: \(r ...
- 【2020五校联考NOIP #2】矩阵
咕咕咕到现在~ 题面传送门 题意: 给出一个 \(n\times n\) 的矩阵 \(A\).要你求有多少个 \(n\times n\) 的矩阵 \(B\) 满足: 每一行都是 \(1\) 到 \(n ...
- 【五校联考1day2】JZOJ2020年8月12日提高组T2 我想大声告诉你
[五校联考1day2]JZOJ2020年8月12日提高组T2 我想大声告诉你 题目 Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ...
随机推荐
- AIApe问答机器人项目Scrum Meeting博客汇总
荡起双桨 Scrum Meeting 博客汇总 一.Alpha阶段 AIApe问答机器人Scrum Meeting 4.23 AIApe问答机器人Scrum Meeting 4.25 AIApe问答机 ...
- redis中lua脚本的简单使用
一.背景 在使用redis的过程中,发现有些时候需要原子性去操作redis命令,而redis的lua脚本正好可以实现这一功能.比如: 扣减库存操作.限流操作等等. redis的pipelining虽然 ...
- CF375D Tree and Queries 题解
感觉CF的题目名都好朴素的样子 你谷链接 首先这题显然是个dsu on tree 但是我不会. 其次这题显然是个莫队.这我会啊! 然后会发现好像不是很对劲.因为每次询问都有一个k,貌似和传统的莫队数颜 ...
- 【BZOJ 1419】Red is good [概率DP]
我 是 Z Z 概率好玄啊(好吧是我太弱.jpg Description 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻 ...
- 重学STM32---(十)之CAN通信(二)
目录 前言 程序编写 主代码 测试 前言 CAN协议是非常难的,但是在stm32中却是简单的,只需要我们配置寄存器即可,,,即使这样,我在学习的时候也遇到了许多困难 程序编写 1.开时钟,不用说 ...
- 【数据结构&算法】05-线性表之数组
目录 前言 线性结构与非线性结构 数组 数组的两个限制 数组的随机访问特性 数组的操作 插入操作 删除操作 数组越界 容器 数组下标 前言 本笔记主要记录数组的一些基础特性及操作. 顺便解答下为什么大 ...
- 记一次CTF比赛过程与解题思路-MISC部分
前言 最近好久没更新博客和公众号了,有朋友问是不是在憋大招,但我不好意思说其实是因为最近一段时间太懒了,一直在当咸鱼- 意识到很久没更新这个问题,我是想写点什么的,但好像一直当咸鱼也没啥可分享的,最近 ...
- java核心技术 第3章 java基本程序设计结构
类名规范:以大写字母开头的名词 若由多个单词组成 每个单词的第一个字母应大写(驼峰命名法) 与.java文件名相同 运行程序:java ClassName(dos命令) 打印语句:System.ou ...
- robotframework-ride快捷方式打不开
我安装的是最新的RIDE2.0属于beta测试中,覆盖了3.8但仍不支持3.9 我的安装环境如下: 安装ride成功,启动ride的时候遇到了如下问题: 一:AttributeError: No at ...
- 数据代理Object.defineProperty()
数据代理: 通过一个对象代理对另一个对象中属性的操作(读/写) 数据代理 Object.defineProperty() Object.defineProperty() 方法会直接在一个对象上定义一个 ...