一、题目
二、解法
想不到啊,这道题居然可以暴力。
由于我们只用比较大小,如果我们先把所有的
a
a
a排序,那么可以把大小比较转化成
01
01
01矩阵,假设我们正在判断
a
[
i
]
[
j
]
a[i][j]
a[i][j],那么小于他的都赋值
0
0
0,其他都赋值
1
1
1,观察a[i][j]<=min{max(a[i][k],a[k][j])}
,可以理解为所有的
a
[
i
]
[
k
]
∣
a
[
k
]
[
j
]
a[i][k]|a[k][j]
a[i][k]∣a[k][j]都不能有
0
0
0,这就可以用
b
i
t
s
e
t
bitset
bitset来做了,利用第一条性质,我们只需要维护行的
b
i
t
s
e
t
bitset
bitset就行了。
b i t s e t bitset bitset的妙用,时间复杂度 O ( n 3 / 64 ) O(n^3/64) O(n3/64)
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 2505;
int read()
{
int num=0,flag=1;
char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
return num*flag;
}
int n,m,a[M][M];
bitset<M> bit[M];
struct node
{
int x,y;
bool operator < (const node &b) const
{
return a[x][y]<a[b.x][b.y];
}
}t[M*M];
void fuck()
{
puts("NOT MAGIC");
exit(0);
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=read();
t[++m]=node{i,j};
}
for(int i=1;i<=n;i++)
{
if(a[i][i]) fuck();
for(int j=1;j<=n;j++)
if(a[i][j]!=a[j][i])
fuck();
}
sort(t+1,t+1+m);
for(int i=1;i<=n;i++)
bit[i].set();
for(int i=1,j=1;i<=m;i++)
{
int x=t[i].x,y=t[i].y;
while(a[t[j].x][t[j].y]<a[x][y])
{
bit[t[j].x][n-t[j].y]=0;
j++;
}
bitset<M> t=bit[x]|bit[y];
if(!t.all()) fuck();
}
puts("MAGIC");
}