题目链接: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(线段树+并查集)的更多相关文章

  1. 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]

    Vladik and Entertaining Flags Time Limit: 20 Sec  Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  3. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  4. codeforces 811E Vladik and Entertaining Flags(线段树+并查集)

    codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...

  5. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  6. 【XSY2707】snow 线段树 并查集

    题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...

  7. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  8. ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集

    正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...

  9. 【CF687D】Dividing Kingdom II 线段树+并查集

    [CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...

随机推荐

  1. Cassandra之Docker环境实践

    Cassandra简介 Cassandra是一个开源分布式NoSQL数据库系统. 它最初由Facebook开发,用于储存收件箱等简单格式数据,集GoogleBigTable的数据模型与Amazon D ...

  2. Placement_pools on Rados-GW

    The purpose of this test is to map a RadosGw Bucket to a specific Ceph pool. For exemple, if using a ...

  3. 9-2、大型项目的接口自动化实践记录----递归判断两个json串是否相等

    1.已知json串构成的情况下判断 先构造一下场景,假设已经把各个数据都移除掉不对比的字段 图1 预期.实际结果,复杂接口返回多层嵌套json时,同下 图2 预期.实际结果值为:{child_json ...

  4. 夯实Java基础(一)——数组

    1.Java数组介绍 数组(Array):是多个相同类型元素按一定顺序排列的集合. 数组是编程中最常见的一种数据结构,可用于存储多个数据,每个数组元素存放一个数据,通常我们可以通过数组元素的索引来访问 ...

  5. JavaScript数据结构——树的实现

    在计算机科学中,树是一种十分重要的数据结构.树被描述为一种分层数据抽象模型,常用来描述数据间的层级关系和组织结构.树也是一种非顺序的数据结构.下图展示了树的定义: 在介绍如何用JavaScript实现 ...

  6. [原创实践]redhat linux 5.3搭建Nexus

    1:下载安装JDK,配置好环境变量(JAVA_HOME等) 下载linux下64位的jdk-7u45-linux-x64.tar.gz(百度网盘下载,官网的jdk-7u51-linux-x64.tar ...

  7. 体验使用MUI上手练习app页面开发

    因为公司安排需要先学习一点app开发,而安排学习的框架就是MUI,上手两天体验还算可以(来自后端人员的懵逼),靠着MUI的快捷键可以快速的完成自己想要的样式模板,更多的交互性的内容则需要使用js来完成 ...

  8. DT-06 For Homekit

    一. 配置DT-06上网 连接此热点,会自动弹出wifi配置页面. 输入选中的路由密码,点 Join加入,如果路由没有出现在列表中,点 Other手工输入(仅支持2.4g路由配置) 二.配置dt-06 ...

  9. docker/kubernetes国内源/镜像源解决方式

    最近在使用kubeadm时,被各种连接不上搞到崩溃.费了很多力气,基本都解决了.这里统一整理了国内的一些镜像源,apt源,kubeadm源等,以便查阅. 国内镜像源 Azure China提供了目前用 ...

  10. 夯实Java基础(十七)——注解(Annotation)

    1.注解概述 从JDK5.0开始,Java增加对元数据(MetaData)的支持,也就是注解(Annotation).其实我们早就已经接触过注解了,例如我们经常在Java代码中可以看到 “@Overr ...