Vladik and Entertaining Flags

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

  n * m的矩形,每个格子上有一个数字代表颜色。

  q次询问,询问[l, r]有几个连通块,若颜色相同并且连通则属于同一个连通块。

Input

  输入第一行n,m,q。
  然后一个n*m的矩形。
  之后q行,每行两个整数l,r。

Output

  输出q行,对于每个询问输出答案。

Sample Input

  4 5 4
  1 1 1 1 1
  1 2 2 3 3
  1 1 1 2 5
  4 4 5 5 5
  1 5
  2 5
  1 2
  4 5

Sample Output

  6
  7
  3
  4

HINT

  1 ≤ n ≤ 10, 1 ≤ m, q ≤ 1e5, 1 ≤ l ≤ r ≤ m

Solution

  我们运用线段树,线段树一个节点i维护这个点表示的[L, R]

  具体维护Li列~Ri列连通块个数Li列连通信息Ri列连通信息Li列编号Ri列编号

  连通信息指的是n个点的连通关系,用一个[10]存下来即可。

  我们现在考虑如何合并两个区间。

  合并的时候,我们先cnt = 两个区间cnt之和,然后考虑左区间的右端信息 以及 右区间的左端信息。

  如果有两个相同的值属于不同连通块,就把它们连通起来,修改一下信息,然后cnt--。显然用并查集处理连通即可。

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9 + ; int get()
{
int res = , Q = ; char c;
while( (c = getchar()) < || c > )
if(c == '-') Q = -;
if(Q) res = c - ;
while( (c = getchar()) >= && c <= )
res = res * + c - ;
return res * Q;
} int n, m, Q;
int col[][ONE];
int l, r; int fat[ONE], total = ;
int Find(int x)
{
if(fat[x] == x) return x;
return fat[x] = Find(fat[x]);
} int Un(int x, int y)
{
int f1 = Find(x), f2 = Find(y);
if(f1 != f2) return fat[f1] = f2, ;
return ;
} struct power
{
int val;
int l[], lid;
int r[], rid;
friend power operator +(power a, power b)
{
power c;
c.val = a.val + b.val;
c.lid = a.lid, c.rid = b.rid; for(int i = ; i <= n; i++)
fat[a.l[i]] = a.l[i], fat[a.r[i]] = a.r[i],
fat[b.l[i]] = b.l[i], fat[b.r[i]] = b.r[i]; for(int i = ; i <= n; i++)
if(col[i][a.rid] == col[i][b.lid])
c.val -= Un(a.r[i], b.l[i]); for(int i = ; i <= n; i++)
c.l[i] = Find(a.l[i]), c.r[i] = Find(b.r[i]); return c;
}
}Node[ONE]; void Build(int i, int l, int r)
{
if(l == r)
{
Node[i].lid = Node[i].rid = l;
for(int j = ; j <= n; j++)
if(col[j - ][l] != col[j][l])
Node[i].l[j] = Node[i].r[j] = ++total, Node[i].val++;
else
Node[i].l[j] = Node[i].r[j] = Node[i].l[j - ];
return;
}
int mid = l + r >> ;
Build(i << , l, mid), Build(i << | , mid + , r);
Node[i] = Node[i << ] + Node[i << | ];
} power Query(int i, int l, int r, int L, int R)
{
if(L <= l && r <= R) return Node[i]; int mid = l + r >> ;
if(!(mid + <= R)) return Query(i << , l, mid, L, R);
else if(!(L <= mid)) return Query(i << | , mid + , r, L, R);
else return Query(i << , l, mid, L, R) + Query(i << | , mid + , r, L ,R);
} int main()
{
n = get(); m = get(); Q = get();
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
col[i][j] = get();
Build(, , m); while(Q--)
{
l = get(), r = get();
power res = Query(, , m, l, r);
printf("%d\n", res.val);
} }

【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]的更多相关文章

  1. Vladik and Entertaining Flags CodeForces - 811E (并查集,线段树)

    用线段树维护每一块左右两侧的并查集, 同色合并时若不连通则连通块数-1, 否则不变 #include <iostream> #include <algorithm> #incl ...

  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. codeforces 811 E. Vladik and Entertaining Flags(线段树+并查集)

    题目链接:http://codeforces.com/contest/811/problem/E 题意:给定一个行数为10 列数10w的矩阵,每个方块是一个整数, 给定l和r 求范围内的联通块数量 所 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 如何防止app接口被别人调用

    app开发的时候,如何保护app的接口呢? 用https是我想到的办法,但是不知道怎么实现,所以就考虑用token,虽然不是绝对有效,但是能防止一般的用户来攻击,高手非要攻击,只能报警了吧. toke ...

  2. Sql server 中关闭ID自增字段(SQL取消ID自动增长)

    sql server在导入数据的时候,有时候要考虑id不变,就要先取消自动增长再导入数据,导完后恢复自增. 比如网站改版从旧数据库导入新数据库,数据库结构不相同,可能会使用insert into xx ...

  3. SQL 语句(增删改查)

    一.增:有4种方法1.使用insert插入单行数据: --语法:insert [into] <表名> [列名] values <列值> 例:insert into Strden ...

  4. 使用vue-cli3新建一个项目,并写好基本配置

    1. 使用vue-cli3新建项目: https://cli.vuejs.org/zh/guide/creating-a-project.html 注意,我这里用gitbash不好选择选项,我就用了基 ...

  5. centOS 中安装 Redis

    之前安装过了 jdk,mysql,tomcat,这次安装 Redis,最开始是将 redis 安装在 windows 下 run 的,这时安装在 Linux 里面试试. 1 . 首先得安装 c环境,用 ...

  6. TTPPRC —— 商业分析模型

    欢迎讨论 : ) 前言1 TTPPRC,是一个为了更容易.透切地进行商业分析而整理出的分析模型.通过这个模型,可以让不具备专业商业知识的大众都能容易得出商业分析结果. 此文是读者阅读原文后,而整理的一 ...

  7. app耗电量测试工具--PowerTutor

    PowerTutor是一款用来测试手机功耗的小工具,它可以只管地展示手机系统主要的组件和各种用户app产生的功耗数据.它可以统计app的屏幕功耗(LCD).CPU功耗以及WiFi和3G网络功耗,我们可 ...

  8. AtCoder Regular Contest 083 C: Sugar Water

    题意 给你一个空杯子,有4种操作: 操作1 加100a克的水 操作2 加100b克的水 操作3 加c克的糖 操作4 加d克的糖 糖的质量不能超过水的质量e/100 糖和水的总质量不能超过f 糖的质量不 ...

  9. 转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)

    PV操作的核心就是 PV操作可以同时起到同步与互斥的作用. 1.同步就是通过P操作获取信号量,V操作释放信号量来进行. 2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到. Java上实现PV ...

  10. [六]SpringBoot 之 连接数据库(mybatis)

    在进行配置之前首先要了解springboot是如何使用纯java代码方式初始化一个bean的 以前的版本是在xml中使用beans标签,在其里面配置bean,那么纯Java代码怎么实现呢? 答案就是使 ...