划年代久远的水

题意

有一个R*C的棋盘,要求在每个格子上填一个非负数,使得对任意一个2*2的正方形区域,左上角和右下角的数字之和等于左下角和右上角的数字之和.有一些格子已经被填上了数字,问现在能否满足要求,输出Yes或No.

R,C<=1e5,已经被填上数字的格子数<=1e5

分析

记i行j列的数字为num[i][j]

假设一个2*2的正方形区域中,左上角,右上角,左下角,右下角依次为a,b,c,d,那么a+d=b+c,也就是说,a-b=c-d,a-c=b-d.

由此我们可以推出这样的结论:

对于任意不同的两行a和b,它们第i列和第j列的数字之差是相同的.即num[a][i]-num[a][j]=num[b][i]-num[b][j]

对于任意不同的两列a和b,它们第i行和第j行的数字之差是相同的.即num[i][a]-num[j][a]=num[i][b]-num[j][b]

于是我们可以用两个带权并查集,分别维护列之间数字之差和行之间数字之差.如果数字之差出现矛盾则无解.同时推出由已知的条件能确定的数值最小的数字,如果这个数字是负数则无解.否则有解.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define GG return puts("No"),0;
const int maxn=100005;
typedef long long ll;
int ufs1[maxn];ll w1[maxn];
int ufs2[maxn];ll w2[maxn];
struct node{
int x,y,val;
void read(){
scanf("%d%d%d",&x,&y,&val);
}
}P[maxn];
bool cmpx(const node &A,const node &B){
return A.x<B.x;
}
bool cmpy(const node &A,const node &B){
return A.y<B.y;
}
int find1(int x){
if(x==ufs1[x])return x;
int rt=find1(ufs1[x]);
w1[x]+=w1[ufs1[x]];
return ufs1[x]=rt;
}
int find2(int x){
if(x==ufs2[x])return x;
int rt=find2(ufs2[x]);
w2[x]+=w2[ufs2[x]];
return ufs2[x]=rt;
}
bool link1(int a,int b,ll w){
if(find1(a)!=find1(b)){
int ra=find1(a),rb=find1(b);
ufs1[ra]=ufs1[rb];
w1[ra]=w+w1[b]-w1[a];
return true;
}else{
return w1[a]==w+w1[b];
}
}
bool link2(int a,int b,ll w){
if(find2(a)!=find2(b)){
int ra=find2(a),rb=find2(b);
ufs2[ra]=ufs2[rb];
w2[ra]=w+w2[b]-w2[a];
return true;
}else{
return w2[a]==w+w2[b];
}
}
ll Min1[maxn],Min2[maxn];
int main(){
int R,C;scanf("%d%d",&R,&C);
for(int i=1;i<=R;++i){
ufs1[i]=i;w1[i]=0;
}
for(int i=1;i<=C;++i){
ufs2[i]=i;w2[i]=0;
}
int n;scanf("%d",&n);
for(int i=1;i<=n;++i)P[i].read();
sort(P+1,P+n+1,cmpx);
for(int i=1;i<n;++i){
if(P[i].x==P[i+1].x){
if(!link2(P[i].y,P[i+1].y,P[i+1].val-P[i].val))GG;
}
}
sort(P+1,P+n+1,cmpy);
for(int i=1;i<n;++i){
if(P[i].y==P[i+1].y){
if(!link1(P[i].x,P[i+1].x,P[i+1].val-P[i].val))GG;
}
}
memset(Min1,0x3f,sizeof(Min1));
memset(Min2,0x3f,sizeof(Min2));
for(int i=1;i<=n;++i){
int rt=find1(P[i].x);
Min1[rt]=min(Min1[rt],P[i].val+w1[P[i].x]);
}
for(int i=1;i<=R;++i){
int rt=find1(i);
Min2[rt]=min(Min2[rt],-w1[i]);
}
for(int i=1;i<=R;++i){
if(ufs1[i]==i&&Min1[i]+Min2[i]<0){
GG;
}
}
memset(Min1,0x3f,sizeof(Min1));
memset(Min2,0x3f,sizeof(Min2));
for(int i=1;i<=n;++i){
int rt=find2(P[i].y);
Min1[rt]=min(Min1[rt],P[i].val+w2[P[i].y]);
}
for(int i=1;i<=C;++i){
int rt=find2(i);
Min2[rt]=min(Min2[rt],-w2[i]);
}
for(int i=1;i<=C;++i){
if(ufs2[i]==i&&Min1[i]+Min2[i]<0)GG;
}
printf("Yes\n");
return 0;
}

CODE FESTIVAL 2016 qualA Grid and Integers的更多相关文章

  1. 【AtCoder】CODE FESTIVAL 2016 qual A

    CODE FESTIVAL 2016 qual A A - CODEFESTIVAL 2016 -- #include <bits/stdc++.h> #define fi first # ...

  2. 【AtCoder】CODE FESTIVAL 2016 qual B

    CODE FESTIVAL 2016 qual B A - Signboard -- #include <bits/stdc++.h> #define fi first #define s ...

  3. 【AtCoder】CODE FESTIVAL 2016 qual C

    CODE FESTIVAL 2016 qual C A - CF -- #include <bits/stdc++.h> #define fi first #define se secon ...

  4. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

  5. Atcoder CODE FESTIVAL 2016 qual C 的E题 Encyclopedia of Permutations

    题意: 对于一个长度为n的排列P,如果P在所有长度为n的排列中,按照字典序排列后,在第s位,则P的value为s 现在给出一个长度为n的排列P,P有一些位置确定了,另外一些位置为0,表示不确定. 现在 ...

  6. [CODE FESTIVAL 2016]Problem on Tree

    题意:给一棵树,对于一个满足以下要求的序列$v_{1\cdots m}$,求最大的$m$ 对$\forall1\leq i\lt m$,路径$(v_i,v_{i+1})$不包含$v$中除了$v_i,v ...

  7. [CODE FESTIVAL 2016]Encyclopedia of Permutations

    题意:给定一个排列,其中有可能有一些未确定的数,求出所有可能的排列的排名之和 首先我们要知道怎么算一个给定排列的排名,设它为$p_{1\cdots n}$ 排名即为比它小的排列数$+1$,对于每一个比 ...

  8. [CODE FESTIVAL 2016]Distance Pairs

    题意:有一个未知的边权为$1$的图,给定所有点到$1$的最短路$a_i$和到$2$的最短路$b_i$,问是否存在这样的图,如果存在,问图中最少有多少条边 先考虑$a_i$,有$a_1=0,a_i\ne ...

  9. CODE FESTIVAL 2016 Grand Final 题解

    传送门 越学觉得自己越蠢--这场除了\(A\)之外一道都不会-- \(A\) 贪心从左往右扫,能匹配就匹配就好了 //quming #include<bits/stdc++.h> #def ...

随机推荐

  1. linux IPC机制学习博客

    要求 研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接 - 共享内存 - 管道 - FIFO - 信号 - 消息队列 研究博客 管道(PIPE) 管道(PIPE): ...

  2. vim 查找

    一.用/和?的区别:/后跟查找的字符串.vim会显示文本中第一个出现的字符串.?后跟查找的字符串.vim会显示文本中最后一个出现的字符串.二.注意事项:不管用/还是?查找到第一个字符串后,按回车,vi ...

  3. 【HEOI2016】排序

    题面 题解 这题好神仙啊... 我们二分这个位置上的数, 然后当\(val[i] \geq mid\)的位置设为\(1\),否则为\(0\) 这样一来,这道题就变成了一个\(01\)序列排序,所以就可 ...

  4. 【LG5017】[NOIP2018pj]摆渡车

    [LG5017][NOIP2018pj]摆渡车 题面 洛谷 题解 震惊!普及组竟然考斜率优化??? 当然有其他的方法 首先我们转化一下模型 此题可以变为: 在一根时间轴上有一些点,每个时间点\(i\) ...

  5. CF 1083 C. Max Mex

    C. Max Mex https://codeforces.com/contest/1083/problem/C 题意: 一棵$n$个点的树,每个点上有一个数(每个点的上的数互不相同,而且构成一个0~ ...

  6. datax源代码编译安装

    what is DataX ? DataX是阿里巴巴集团内被广泛使用的离线数据同步工具/平台. 实现包括MySQL,SQL Server,Oracle,PostgreSQL,HDFS,Hive,HBa ...

  7. [转]RobotFrameWork+APPIUM实现对安卓APK的自动化测试----第一篇【安装】

    前言:关于RobotFrameWork+APPIUM实现对安卓APK的自动化测试的文章都是取自于乐于分享知识于网络的好心人们,所以我也希望我的知识可以分享给大家. 首先我们先罗列一下我们要安装的软件 ...

  8. 第五章Web应用与应用层协议

    Web应用与应用层协议 本篇博文中的主要参考文献是<计算机网络高级教程>,分别是吴功宜老先生和吴英教授合著.这部教程是我研究生老师所推荐的网络必读科目,由于该教程讲解的基础知识详细,但内容 ...

  9. 接口自动化·分享·第二篇·你必须了解的HttpRequest和HttpResponse

    完成一个接口调用其实就是完成了一次http请求,所以你必须要清楚一个http请求的组成. 一次完整的请求包含:请求+响应. 一.HttpRequest请求对象 要调用一个接口,首先要准备的是一个请求对 ...

  10. Windows下Mongo分片及集群

    这里简单介绍一下windows下mongodb的分片设置和集群搭建,希望能够为迷茫的新手起到一点点作用.其实windows下与linux下思路是一致的,只是绑定时的ip,与端口号不同,linux下可以 ...