习题:Magic Matrix(bitset优化暴力)

题目

传送门

思路

阿这,这道题确实没有想到会是如此暴力的时间复杂度\(O(\frac{n^3}{32})\)

对于第一和第二个限制,相信可以不用过多阐释,直接暴力就可

看到这个常数,最容易想到的就是\(bitset\)

我们考虑按照权值的大小来填,填了的位置赋值为1,没有填的赋值为0

考虑我们要将权值为\(val\)的位置填上\(1\)

首先可以知道的一点权值小于\(val\)的位置上一定全是1

对于一个\(val\),其他的位置的值具体是什么其实并不重要,重要的是比val大还是比val小

对于\(a_{i,k}\)\(a_{k,j}\)这两个位置,首先我们需要取一个max,用\(\&\)操作即可实现

我们考虑如果将i这一行和j这一列并起来,如果某一位上是1,即表示即使这意味上大的数依旧比val小,即不合法

代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
struct node
{
    int val;
    int x,y;
    friend bool operator < (const node &a,const node &b)
    {
        return a.val<b.val;
    }
};
int n;
int a[2505][2505];
bitset<2505> g1[2505];
bitset<2505> g2[2505];
vector<node> v;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&a[i][j]);
            v.push_back((node){a[i][j],i,j});
        }
    for(int i=1;i<=n;i++)
    {
        if(a[i][i]!=0)
        {
            cout<<"NOT MAGIC";
            return 0;
        }
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]!=a[j][i])
            {
                cout<<"NOT MAGIC";
                return 0;
            }
        }
    }
    sort(v.begin(),v.end());
    v.push_back((node){-1,0,0});
    for(int i=0;i<v.size()-1;i++)
    {
        int l=i;
        while(v[i].val==v[i+1].val)
            i++;
        for(int j=l;j<=i;j++)
        {
            if((g1[v[j].x]&g2[v[j].y])!=0)
            {
                cout<<"NOT MAGIC";
                return 0;
            }
        }
        for(int j=l;j<=i;j++)
        {
            g1[v[j].x][v[j].y]=1;
            g2[v[j].y][v[j].x]=1;
        }
    }
    cout<<"MAGIC";
    return 0;
}
/*
0
*/
posted @ 2020-07-20 10:36  loney_s  阅读(136)  评论(0)    收藏  举报