【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 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ...
随机推荐
- 如何使用远程工具连接Linux服务器
大家好,今天我想和大家分享一下Linux如何连接远程控制工具我们都知道,Linux是著名的开源服务器操作系统,而在运维工程师的实际工作当中,我们不大可能时时刻刻都在服务器本地操作.因此这时,我们要用远 ...
- JVM:类加载与字节码技术-1
JVM:类加载与字节码技术-1 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 内容 类文件结构 字节码指令 下面的内容在后续笔记中: 编译期处理 类加载阶段 类 ...
- 2021.8.15考试总结[NOIP模拟40]
T1 送花 线段树.枚举右端点,线段树记录左端点对应的值. 每次对当前颜色上上次出现的位置到上次出现的位置区间减,上次出现的位置到当前位置区间加. $code:$ 1 #include<bits ...
- windows下wchar_t的问题
使用vs新建工程或者编译工程的时候默认在编译设置里面讲wchar_t设置为内置类型,如下图: 但是在编译相互依赖的工程的时候,如果有的工程不将wchar_t设置为内置类型的时候,将会出现链接错误,需要 ...
- openmp学习心得(一)
主要在vs2015下使用OMP,写一些自己omp的学习心得: 一.在VS2015下OpenMP的使用: 1.VS2015也仅仅支持OpenMP2.0版本,VS对OpenMP的支持并不太好. 2.在VS ...
- 使用jQuery-UI来实现一个Ajax的自动完成功能(自动填充搜索框的下拉值)
首先你要在.net拓展包中去搜索 jquery ui (Combined Libray)安装这么个文件 第二部 在控制器中添加我们根据输入搜索框的值获取符合的记录集的action 第三步 有了 ...
- 第01课 OpenGL窗口(4)
下面的代码处理所有的窗口消息.当我们注册好窗口类之后,程序跳转到这部分代码处理窗口消息. LRESULT CALLBACK WndProc( HWND hWnd, // 窗口的句柄 UINT uMsg ...
- ELK集群之grafana(8)
Grafana的安装和读取ES数据 模拟es数据产生sjgtest.py import time import datetime from elasticsearch import Elasticse ...
- JMeter跨线程组保持登录(多线程组共享cookie)
使用__setProperty设置全局变量: 1.jmeter中创建一个登录请求,然后执行,察看结果树-->查看返回cookie信息,我的是在Response data中的 Response h ...
- LeetCode 113. 路径总和 II C++
提交结果:内存超100%,用时超69% /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNo ...