CometOJ contest#13「佛御石之钵 -不碎的意志-」(并查集+Set)

题意: n ∗ m , n , m ≤ 1 e 3 n*m,n,m\le 1e3 nm,n,m1e3 的矩阵,矩阵赋 1,查询 1 的连通块个数, q ≤ 3 e 4 q\le3e4 q3e4 次修改
想到用并查集维护连通块,每次暴力将矩阵中的合并肯定要凉
于是把矩阵中为 0 的踢出来合并
考虑到 n q nq nq 可能可以卡过,于是用 s e t set set 维护每一行的为 0 0 0 的点,每次踢出来暴力改成 1 并与周围的合并
显然每个点只会出来一次,复杂度 O ( q n l o g ( n ) + n 2 l o g ( n ) ) O(qnlog(n)+n^2log(n)) O(qnlog(n)+n2log(n))

#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
	return cnt * f; 
}
cs int N = 1005;
int n, m, q, sum; 
char mp[N][N];
set<int> S[N];
typedef set<int>::iterator Int;
int idx(int x, int y){ return (x - 1) * m + y;}
int fa[N * N];
int find(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]);}
void merge(int x, int y){
	++sum;
	if(x > 1 && mp[x - 1][y] == '1'){
		int fx = find(idx(x, y)), fy = find(idx(x - 1, y));
		if(fx ^ fy) fa[fx] = fy, --sum;
	} 
	if(y > 1 && mp[x][y - 1] == '1'){
		int fx = find(idx(x, y)), fy = find(idx(x, y - 1));
		if(fx ^ fy) fa[fx] = fy, --sum;
	}
	if(x < n && mp[x + 1][y] == '1'){
		int fx = find(idx(x, y)), fy = find(idx(x +1, y));
		if(fx ^ fy) fa[fx] = fy, --sum;
	}
	if(y < m && mp[x][y + 1] == '1'){
		int fx = find(idx(x, y)), fy = find(idx(x, y + 1));
		if(fx ^ fy) fa[fx] = fy, --sum;
	} 
}
int main(){
	n = read(), m = read();
	for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) fa[idx(i, j)] = idx(i, j); 
	for(int i = 1; i <= n; i++){
		scanf("%s", mp[i] + 1);
		for(int j = 1; j <= m; j++){
			if(mp[i][j] == '0') S[j].insert(i);
			else merge(i, j);
		} 
	}
	q = read();
	while(q--){
		int x1 = read(), y1 = read(), x2 = read(), y2 = read();
		for(int i = y1; i <= y2; i++){
			int top = 0;
			Int it = S[i].lower_bound(x1);
			while(it != S[i].end()){
				int nx = *it;
				if(nx > x2) break;
				merge(nx, i); mp[nx][i] = '1';
				S[i].erase(it++);
			}
		}
		cout << sum << '\n'; 
	} return 0;
}

以下是口胡时间 「蓬莱的弹枝 -七色的弹幕-」
在这里插入图片描述
高级数据结构不如暴力数据结构 ---- ldx 神仙
考虑分块
首先挪一位,就是把一个块的最前放到一个块的最后,可以每个块维护一个队列
两头暴力重构
全部加 1 就是打一个 t a g tag tag,然后挪块的时候可能需要改一下 t a g tag tag
对于 3,每个块维护一个桶,装 a i a_i ai 的出现次数,非常暴力,查询每个块扫一遍,如果有就块内扫一遍
然后 a i ≤ 1 e 5 a_i\le 1e5 ai1e5 Δ ≤ 1 e 5 \Delta\le 1e5 Δ1e5,数最大是 2 e 5 2e5 2e5,但挪块可能变负,平移一波开到 3 e 5 3e5 3e5
算了一些块最多 200 200 200 个,大小 500 500 500 左右

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值