E. Binary Matrix 【并查集】2500

E. Binary Matrix

图片说明

图片说明

题意

给一个很大的矩阵,问联通块的个数是多少。其中因为矩阵非常大,用的16进制输入的。

解法

这题非常卡常,光是读入量就已经1.6e7了,所以这里我使用了getchar()来读入。
然后对于联通块的个数,就是总的1个数 - 并查集合并的次数

考虑一行一行处理并查集,同一行遍历相邻两个字符,进行合并,不同行,就当前行跟上一行进行合并,在同为1的时候。
对于并查集的fa[]数组,其值需要再下一次做并查集的时候进行改变。

上一行的fa[]数组,范围是,下一行是, 当处理完这两行的后,要把下一行作为下一次操作的上一行,要做以下2个操作:

  1. 将字符串进行拷贝到上一行
  2. 将fa[]数组映射到,这样就不含引起并查集冲突。

代码

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define debug_in  freopen("in.txt","r",stdin)
#define debug_out freopen("out.txt","w",stdout);
#define pb push_back
#define all(x) x.begin(),x.end()
#define fs first
#define sc second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
const ll maxn = 1e5+100;
const ll maxM = 1e6+10;
const ll inf = 1e8;
const ll inf2 = 1e17;

template<class T>void read(T &x){
    T s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    x = s*w;
}
template<class H, class... T> void read(H& h, T&... t) {
    read(h);
    read(t...);
}

template<class T> void pt(T x){
    cout<<x<<" ";
}

template <typename T, typename... Args>
void pt(const T& t, const Args& ... data){
    cout<<t<<" ";
    pt(data...);
}


//--------------------------------------------

int N,M;
char line1[maxn];
char line2[maxn];
int fa[maxn*2];
int ind[maxn*2];
void work(char line[],int idx,char c){
    int v;
    if('0' <=c && c <='9') v = c - '0';
    else v = 10 + c-'A';
    int w[4],tail = 3;
    for(int i = 0;i<4;i++) w[i] = 0;
    while(v){
        w[tail--] = v%2;
        v/=2;
    }
    for(int i = 0;i<4;i++){
        line[idx+i] = '0'+w[i];
    }
}
int total = 0,bin = 0;
int find(int x){
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void solve(){
    for(int j = 1;j<=M;j++) fa[M+j] = M+j;
    for(int j = 2;j<=M;j++){
        if(line2[j-1] == '1' && line2[j] == '1'){
            int fx = find(M + j-1),fy = find(M + j);
            if(fx != fy){
                bin++;
                fa[fx] = fy;
            }
        }
    }
    for(int j = 1;j<=M;j++){
        if(line1[j] == '1' && line2[j] == '1'){
            int fx = find(j),fy = find(M+j);
            if(fx != fy){
                bin++;
                fa[fx] = fy;
            }
        }
    }
}
void init(){ //把下一行的信息,拷贝到上一行,并重新映射fa数组
    for(int i = 1;i<=2*M;i++) ind[i] = 0;
    for(int j = 1;j<=M;j++) fa[M+j] = find(M+j);
    for(int j = 1;j<=M;j++){
        if(ind[fa[M+j]] == 0){
            ind[fa[M+j]] = j;
        }
    }
    for(int j = 1;j<=M;j++){
        fa[j] = ind[fa[M+j]];
    }
    for(int j = 1;j<=M;j++) line1[j] = line2[j];
}
int main(){
    // debug_in;

    read(N,M);
    for(int j = 1;j<=M;j++) fa[j] = j;
    for(int i = 1;i<=N;i++){
        for(int j = 1;j<=M/4;j++){
            char c;c = getchar();
            while(!(('0'<=c &&c <='9') || ('A'<=c && c<='F'))) c = getchar();//加快读入
            work(line2,(j-1)*4 + 1,c); //填入到字符数组中
        }
        for(int j = 1;j<=M;j++) if(line2[j] == '1') total++;
        if(i == 1) { //第一行特殊处理
            for(int j = 1;j<=M;j++) fa[M + j] = M + j;
            for(int j = 2;j<=M;j++) {
                if(line2[j-1] == '1' && line2[j] == '1'){
                    int fx = find(M + j-1),fy = find(M + j);
                    if(fx != fy){
                        bin++;
                        fa[fx] = fy;
                    }
                }
            }
            init();
        }
        else {
            solve();
            init();
        }

    }
    printf("%d\n",total - bin);


    return 0;
}
全部评论

相关推荐

头像
04-27 15:11
已编辑
华东师范大学 算法工程师
暑期实习从2月开始投,面了两个月,流程该挂的都挂完了,腾讯字节一共号称是1.7w个hc,不知道都发给谁了,估计今年秋招要难顶。Timeline米哈游、美团、蚂蚁、微软等公司直接简历挂穿,没进面。携程:3.3&nbsp;投递、测评3.12&nbsp;笔试3.18&nbsp;一面3.25&nbsp;二面4.13&nbsp;ai面(hr面)4.14&nbsp;英语测评4.23&nbsp;offer(已拒)腾讯:2.6&nbsp;测评2.28&nbsp;wxg一面3.5&nbsp;wxg二面(挂)3.11&nbsp;teg一面3.21&nbsp;teg二面(取消)3.31&nbsp;teg一面4.10&nbsp;teg二面(挂)4.21&nbsp;wxg一面4.24&nbsp;wxg二面(挂)字节:1.28&nbsp;aml约面(取消)3.17&nbsp;火山一面(挂)4.8&nbsp;aml一面(挂)4.20&nbsp;抖音data一面(挂)阿里:3.23&nbsp;投递、测评3.28&nbsp;笔试3.31&nbsp;淘天一面4.8&nbsp;钉钉一面4.9&nbsp;淘天二面4.10&nbsp;阿里控股一面4.12&nbsp;钉钉二面(取消)4.15&nbsp;淘天hr面4.16&nbsp;淘天offer(已接)4.21&nbsp;高德一面(取消)4.22&nbsp;淘宝闪购一面(取消)面试最大的感触是,现在撞上ai转型,一堆老业务急着转向,新业务非常不成熟,研究型的组bar非常高根本进不去,业务侧挂着算法的岗位干的都是工程活,面试却又要问算法,另外agent的落地也远没有那么广,绝大多数还是那套写死的系统调一下llm&nbsp;api或者做做rag,其余少部分真的在搭agent的,基本不能在线上服务用什么很智能的模型,现阶段成本太高,进去大概率就是给垃圾模型从工程方面兜底,除了业务场景的应用和数据经验以外,技术方面很难有什么提升。算法岗做不了基模的还是去搜广推好,之前判断失误了完全没投,秋招不知道还进不进得去。
嵌入式的小白:不错啊,淘天也是挺好的,恭喜
我的求职进度条
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务