codeforces 811 E. Vladik and Entertaining Flags(线段树+并查集)
题目链接:http://codeforces.com/contest/811/problem/E
题意:给定一个行数为10 列数10w的矩阵,每个方块是一个整数, 给定l和r 求范围内的联通块数量 所谓联通块即数字相等
题解:显然可以用线段树来维护一下,一共就10行。线段树唯一难处理的就是push_up不好弄,这一要利用一下并查集,因为求的是连通块
的个数。具体看一下代码的注释。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 1e5 + 10;
struct TnT {
int l , r , sum;
int lsum[11] , rsum[11];
}T[M << 2];
int f[M << 4] , a[11][M];
int n , m , q , tot;
//并查集并的是她们连通块的种类。
void init() {
for(int i = 1 ; i <= n * m ; i++) {
f[i] = i;
}
}
int find(int x) {
if(x == f[x]) return x;
int tmp = find(f[x]);
return f[x] = tmp;
}
TnT push_up(int mid , TnT le , TnT re) {
TnT ans;
ans.sum = le.sum + re.sum;
for(int j = 1 ; j <= n ; j++) {
f[le.lsum[j]] = le.lsum[j];
f[le.rsum[j]] = le.rsum[j];
f[re.lsum[j]] = re.lsum[j];
f[re.rsum[j]] = re.rsum[j];
}//这里一定要这样赋值一下因为合并的时候这两部分肯定不属于同意连通块,所以不能让她们的父亲相同,而且她们的父亲会在合并的时候变成相同的所以这里要每次给她们定一个新父亲。
for(int j = 1 ; j <= n ; j++) {
if(a[j][mid] == a[j][mid + 1]) {
int t1 = find(le.rsum[j]) , t2 = find(re.lsum[j]);
if(t1 != t2) {
ans.sum--;
f[t1] = t2;
}//显然如果不是相同父亲的sum--
}
}
for(int j = 1 ; j <= n ; j++) {
ans.lsum[j] = find(le.lsum[j]);
ans.rsum[j] = find(re.rsum[j]);
}//pushup一下ans的lsum于rsum
ans.l = le.l , ans.r = re.r;
return ans;
}
void build(int i , int l , int r) {
int mid = (l + r) >> 1;
T[i].l = l , T[i].r = r , T[i].sum = 0;
if(l == r) {
for(int j = 1 ; j <= n ; j++) {
if(a[j][l] == a[j - 1][l]) {
T[i].lsum[j] = T[i].rsum[j] = T[i].lsum[j - 1];//如果相邻两个一样那么她们肯定属于一个连通块所以连通块下表一样,
}
else {
T[i].lsum[j] = T[i].rsum[j] = ++tot;
T[i].sum++;
}
}
return ;
}
build(i << 1 , l , mid);
build((i << 1) | 1 , mid + 1 , r);
T[i] = push_up(mid , T[i << 1] , T[(i << 1) | 1]);
}
TnT query(int i , int l , int r) {
int mid = (T[i].l + T[i].r) >> 1;
if(T[i].l == l && T[i].r == r) {
return T[i];
}
T[i] = push_up(mid , T[i << 1] , T[(i << 1) | 1]);
if(mid < l) return query((i << 1) | 1 , l , r);
else if(mid >= r) return query(i << 1 , l , r);
else {
return push_up(mid , query(i << 1 , l , mid) , query((i << 1) | 1 , mid + 1 , r));
}
}
int main() {
scanf("%d%d%d" , &n , &m , &q);
tot = 0;
for(int i = 1 ; i <= n ; i++) {
for(int j = 1 ; j <= m ; j++) {
scanf("%d" , &a[i][j]);
}
}
init();
build(1 , 1 , m);
while(q--) {
int x , y;
scanf("%d%d" , &x , &y);
printf("%d\n" , query(1 , x , y).sum);
}
return 0;
}
codeforces 811 E. Vladik and Entertaining Flags(线段树+并查集)的更多相关文章
- 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]
Vladik and Entertaining Flags Time Limit: 20 Sec Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- codeforces 811E Vladik and Entertaining Flags(线段树+并查集)
codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【XSY2707】snow 线段树 并查集
题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...
- bzoj 2054: 疯狂的馒头(线段树||并查集)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...
- ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集
正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...
- 【CF687D】Dividing Kingdom II 线段树+并查集
[CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...
随机推荐
- Mac 10.14.4 编译openjdk1.9源码 及集成clion动态调试
警告⚠️:本文耗时很长,先做好心理准备:编译openjdk源码需要很大的耐心,因为要踩很多坑,解决很多问题,本人从编译开始到结束用了两天时间,按照本篇教程踩坑会少许:谢谢观看 一.获取openjdk源 ...
- .net core 实现基于 cron 表达式的任务调度
.net core 实现基于 cron 表达式的任务调度 Intro 上次我们实现了一个简单的基于 Timer 的定时任务,详细信息可以看这篇文章. 但是使用过程中慢慢发现这种方式可能并不太合适,有些 ...
- 关于HostnameVerifier接口的解读
在项目中我们需要调用https接口请求.我们使用httpClient,构建HttpClient对象时涉及到使用HostnameVerifier接口实例. HostnameVerifier接口定义如下: ...
- vue通信、传值的多种方式(详细)
转载自https://blog.csdn.net/qq_35430000/article/details/79291287
- sed流编辑器
一.前言 (一).sed 工作流程 sed 是一种在线的.非交互式的流编辑器,它一次处理一行内容.处理时,把当做前处理的行存储在临时缓存区中,成为“模式空间”(pattern space),接着用se ...
- grep使用集合
一.grep使用 (一).选项 -a 不要忽略二进制数据. -A<显示列数> 除了显示符合范本样式的那一行之外,并显示该行之后的内容. -b 在显示符合范本样式的那一行之外,并显示该行之前 ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)
序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...
- Hadoop单机、伪分布式、分布式集群搭建
JDK安装 设置hostname [root@bigdata111 ~]# vi /etc/hostname 设置机器hosts [root@bigdata111 ~]# vi /etc/hosts ...
- GD32电压不足时烧写程序导致程序运行异常的解决方法
一直使用的GD32F450前段时间遇到这样一个问题,当使用J-Link供电给板子烧写程序之后,程序运行缓慢,就像运行在FLASH高速部分之外一样,但是如果使用外部供电烧写,就不会出现这个问题,而且一旦 ...
- 【0728 | 预习】第三篇 Python基础
第三篇 Python基础预习 Part 1 变量 一.什么是变量? 二.为什么要有变量? 三.定义变量 四.变量的组成 五.变量名的命名规范 六.变量名的两种风格 Part 2 常量 Part 3 P ...