首页 > 其他分享 >AtCoder Beginner Contest 277 F Sorting a Matrix

AtCoder Beginner Contest 277 F Sorting a Matrix

时间:2022-11-13 00:02:49浏览次数:85  
标签:偏序 AtCoder Sorting Matrix 同一 int ll vector include

Sorting a Matrix

拓扑序

首先可以明确无论怎么交换行列,原本在同一行或者同一列的元素,还是会处于同一行或者同一列

  • 条件一

每行每行地看,如果能满足从小到大的条件,说明第 \(i\) 行的值域 \([min_i, max_i]\) 与 第 \(i - 1\) 行的值域 \([min_{i - 1}, max_{i - 1}]\) 必然有以下关系:

\(max_{i - 1} \le min_i\)

因此提出每一行的值域范围,判断一下是否满足该条件,如果碰到 \(0\) 可以直接跳过,如果该行全 \(0\) 的话,记得特判一下(丢掉)

  • 条件二

在同一行里,如果想做到从小到大,必然有一个偏序关系:如果有 \(a_{ij} < a_{ik}\),那么第 \(j\) 列肯定在第 \(k\) 列的前面。因此对于每一行中的偏序关系都构建出来,如果这个偏序关系有拓扑序,则说明有解

记得要跳过 \(0\)

还有一个要处理的地方就是,如果同一行内有若干个数字等于 \(x\),有若干个数字等于 \(x + 1\),则构建偏序关系的时候是要两两相连的,显然复杂度会退化成 \(O((nm)^2)\)

我的处理方式是缩点,然后构建边,就变成了 \(O(nm)\)

其实这题总结下来就是列和行的拓扑序若能保证,则有解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
#include <ctime>
#include <cstdlib>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e6 + 10;
const ll inf = 1e17 + 10;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    vector<vector<int>> matrix(n, vector<int>(m, 0)), gra(m + n * m);
    vector<int> in(m + n * m, 0);
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            cin >> matrix[i][j];
    vector<array<int, 2>>leg(n);
    int tp = m - 1;
    for(int i=0; i<n; i++)
    {
        leg[i] = {n * m * 2, 1};
        int cnt = 0;
        for(int j=0; j<m; j++)
        {
            cnt += matrix[i][j] == 0;
            if(matrix[i][j] == 0) continue;
            leg[i][0] = min(leg[i][0], matrix[i][j]);
            leg[i][1] = max(leg[i][1], matrix[i][j]);
        }
        if(cnt == m) leg[i] = {1, 1};
        vector<array<int, 2>>a(m);
        for(int j=0; j<m; j++) a[j] = {matrix[i][j], j};
        sort(a.begin(), a.end());
        int l = 0, r = 0;
        while(l < m && a[l][0] == 0) l++;
        r = l;
        int pre = 0;
        while(l < m)
        {
            while(r < m && a[l][0] == a[r][0]) r++;
            tp++;
            for(int j=l; j<r; j++)
            {
                gra[a[j][1]].push_back(tp);
                in[tp]++;
            }
            if(pre) for(int j=l; j<r; j++)
            {
                gra[pre].push_back(a[j][1]);
                in[a[j][1]]++;
            }
            l = r;
            pre = tp;
        }
    }
    sort(leg.begin(), leg.end());
    int f = 1, now = 0;
    for(auto [l, r] : leg)
    {
        if(l < now) f = 0;
        now = r;
    }
    queue<int>q;
    for(int i=0; i<=tp; i++) if(in[i] == 0) q.push(i);
    while(q.size())
    {
        int now = q.front();
        q.pop();
        for(int nex : gra[now])
        {
            in[nex]--;
            if(in[nex] == 0) q.push(nex);
        }
    }
    for(int i=0; i<=tp; i++) if(in[i] > 0) f = 0;
    if(f) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

标签:偏序,AtCoder,Sorting,Matrix,同一,int,ll,vector,include
From: https://www.cnblogs.com/dgsvygd/p/16885154.html

相关文章

  • AtCoder Beginner Contest 277 E Crystal Switches
    CrystalSwitches分层图+\(01bfs\)按钮的操作就是走分层图的边因此就构建两张图,然后将特殊点加一个双向边\(01bfs\)跑一下就行#include<iostream>#include<cstd......
  • AtCoder Beginner Contest 277 题解
    掉大分力(悲A-^{-1}直接模拟。#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false)#defineTIEcin.tie(0),cout.tie(0)#defineintlonglongusing......
  • Atcoder ARCaea 118 B
    我又来啦!光&对立题面小A正在调配药剂。传说中有一种最强的药剂,叫做Tempestissimo,用了$K$种药剂,标号$1\simK$。当时(由于这药剂只调配过一次)分别用了$......
  • 塔防(cover)Atcoder/Codeforces的某道题
    题目背景在某个塔防游戏中,有一种防御塔,可以攻击到上下左右四个方向以及自身位置的敌人。题目描述塔防游戏的⼀个关卡地图可以看作⼀个的矩阵,也就是⾏,列的矩阵。其......
  • AtCoder Regular Contest 149 D Simultaneous Sugoroku
    很妙的一个题。没法用数据结构直接维护点的移动。可以挖掘一些性质。发现对于两个点\(x\)和\(-x\),它们的移动关于原点对称。可以根据对称性维护森林。维护当前的区间......
  • atcoder abc 276
    A-Rightmost题意:给定一个字符串,确定字母a,最后出现的位置,若字符串中没有出现字母a,则输出-1思路:遍历统计代码:#include<bits/stdc++.h>usingnamespacestd;int......
  • Atcoder Grand Contest 004(A~F)
    这场半VP做的,就不分赛时赛后写了,直接放每道题的解法。A-DivideaCuboid当某一维的长度为偶数的时候,显然可以在这一维的中间切,两部分方块的最小差为\(0\)。当每一......
  • AtCoder Beginner Contest 275
    A-FindTakahashi找到序列中最高的数存在的位置#include<bits/stdc++.h>usingnamespacestd;intread(){intx=0,f=1,ch=getchar();while((c......
  • Atcoder Beginner Contest 276(A~G)
    赛时A简单字符串处理;B简单vector处理;C找上一个排列。D找到每一个数因子\(2\)的个数和\(3\)的个数,并判断除去这些因子之后剩下的值是否相同,若不同则不能满足条......
  • AtCoder Beginner Contest 276
    A-Rightmost#include<bits/stdc++.h>usingnamespacestd;int32_tmain(){strings;cin>>s;for(inti=s.size();i>=1;i--)i......