USACO 2020 OPEN Silver Problem 3. The Moo Particle
题意:

解法:
首先给出在本题中连通和连通块的定义:
连通:
两个粒子a,b连通,当且仅当ax≤bx、ay≤by或者bx≤ax、by≤ay。

如图,A,B两粒子是连通的,而C、D不是。
可以看出,本题中连通的定义类似于无向边。
连通块:
一个有n个粒子的粒子集合S被称为连通块,当且仅当该集合内的粒子可以通过相互作用仅留下任意一个粒子。

左侧的A图中的四粒子属于同一连通块,而右侧的B图中四粒子分别属于两个连通块。
50分暴力:
显然,最少留下的粒子(以下简称为点)数等于连通块的总数,故本题可以转化为求最小的连通块划分数。通过该结论可以写出50分暴力(n≤1000)。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + ;
int n, ans, fa[N], dx[N], dy[N];
bool cont (int x, int y) {
if (dx[x] <= dx[y] && dy[x] <= dy[y])
return true;
if (dx[x] >= dx[y] && dy[x] >= dy[y])
return true;
return false;
}
int find (int x) {
if (x != fa[x])
return fa[x] = find (fa[x]);
return x;
}
void merges (int x, int y) {
int xx = find (x), yy = find (y);
if (xx == yy)
return ;
fa[xx] = yy;
return ;
}
int main () {
freopen ("moop.in", "r", stdin);
freopen ("moop.out", "w", stdout);
scanf ("%d", &n);
for (int i = ; i <= n; i ++) {
scanf ("%d %d", &dx[i], &dy[i]);
fa[i] = i;
}
for (int i = ; i <= n; i ++)
for (int j = i + ; j <= n; j ++)
if (cont (i, j))
merges (i, j);
for (int i = ; i <= n; i ++)
if (fa[i] == i)
ans ++;
printf ("%d\n", ans);
return ;
}
满分解法:
O(n2)暴力连边判断连通块的方法显然是不行的。所以需要找到一种快速划分连通块的方法。
考虑按每个点的x坐标排序并记录排序完成后的y坐标并用数组(a)记录,则可以快速离散化所有点的坐标。(当两点x相同时两点必定连通,故不需要特别讨论x坐标相同的情况)
考虑一个在x轴上连续的点集,满足该点集最左侧的点的y坐标比最右侧的点的y坐标小。(如图)

L、R分别为该点集中最左侧、最右侧的点。
显然,L与R连通。
将点集中剩下的点分为三类:
A类:在R点左上方(如A点)
B类:在R点左下方并且在L点右上方(如B点)
C类:在L点右下方(如C点)
对每类点的连通情况进行讨论:
A类:
因为A点在R点左上方,故A点y坐标比L大、x坐标比L大。所以该点与L点连通。
B类:
因为B点在L点右上方和R点左下方,故与L、R点都连通。
C类:
因为C点在L点右下方,故C点y坐标比R小,x坐标比R小,所以该店与R点连通。
综上所述,A、B、C类点都与L、R中的一点连通,而L又与R点连通。
可得到结论:任意一个满足最左侧的点的y坐标比最右侧的点的y坐标小的在x轴上连续的点集都满足连通块的定义。
由此可以得到一种O(n)的贪心的连通块划分方法:从左往右扫描所有点,若当前点的y值小于上一个点所属的连通块的L点的y值,则从该点开始新建一个连通块,并记录该点的y坐标。
但此贪心方法有明显错误,如图:

按照这种贪心方法,该点集会被划分为(A、B、C)和(D、E)两个连通块。实际上(A、B、C、D、E)即为一个连通块。
此时可以发现,若记录划分到当前点前每个连通块的L点的y坐标,并在每个点用二分算法判断该点y坐标最大大于哪个L点(设为l点)y坐标并将l点之后的所有点与l点合并为一个连通块,就可以在logn时间内更加准确地判断出到目前点为止最小的连通块划分数。
但这种判断方法仍然有问题,如图:

点(A、B、C、D、E、F)为一个连通块,但按照当前贪心方法会划分出(A、B、C、D、E)和(F)两连通块。故我们需要进一步优化贪心方法。
在原贪心方法中,我们记录的是到目前点为止,划分出的所有连通块的L节点的y值,但并入一个连通块并不一定需要大于该连通块的L点,仅需要在该联通块最右侧的点的右侧并大于该连通块的最小点即可。
故在合并连通块的时候,可以把原连通块的L节点的y值更新为现连通块L节点的y值。
这样即可求出最小连通块划分数。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + ;
int n, a[N], cnt, mn[N];
pair <int, int> p[N];
int main () {
freopen ("moop.in", "r", stdin);
freopen ("moop.out", "w", stdout);
scanf ("%d", &n);
for (int i = ; i <= n; i ++)
scanf ("%d %d", &p[i].first, &p[i].second);
sort (p + , p + n + );
for (int i = ; i <= n; i ++)
a[i] = p[i].second;
for (int i = ; i <= n; i ++) {
if (i == || -mn[cnt] > a[i]) {
cnt ++;
mn[cnt] = -a[i];
continue ;
}
if (cnt == )
continue;
if (-mn[cnt - ] <= a[i]) {
int mnn = mn[cnt];
int ls = lower_bound (mn + , mn + cnt + , -a[i]) - mn;
cnt = ls;
mn[cnt] = mnn;
}
}
printf ("%d\n", cnt);
return ;
}
USACO 2020 OPEN Silver Problem 3. The Moo Particle的更多相关文章
- USACO翻译:USACO 2013 NOV Silver三题
USACO 2013 NOV SILVER 一.题目概览 中文题目名称 未有的奶牛 拥挤的奶牛 弹簧牛 英文题目名称 nocow crowded pogocow 可执行文件名 nocow crowde ...
- USACO翻译:USACO 2013 DEC Silver三题
USACO 2013 DEC SILVER 一.题目概览 中文题目名称 挤奶调度 农场航线 贝西洗牌 英文题目名称 msched vacation shuffle 可执行文件名 msched vaca ...
- USACO翻译:USACO 2014 DEC Silver三题
USACO 2014 DEC SILVER 一.题目概览 中文题目名称 回程 马拉松 奶牛慢跑 英文题目名称 piggyback marathon cowjog 可执行文件名 piggyback ma ...
- USACO翻译:USACO 2012 FEB Silver三题
USACO 2012 FEB SILVER 一.题目概览 中文题目名称 矩形草地 奶牛IDs 搬家 英文题目名称 planting cowids relocate 可执行文件名 planting co ...
- USACO翻译:USACO 2014 FEB SILVER 三题
USACO 2014 FEB SILVER 一.题目概览 中文题目名称 自动打字 路障 神秘代码 英文题目名称 auto rblock scode 可执行文件名 auto rblock scode 输 ...
- USACO 2013 Nov Silver Pogo-Cow
最近因为闲的蛋疼(停课了),所以开始做一些 USACO 的银组题.被完虐啊 TAT 貌似 Pogo-Cow 这题是 2013 Nov Silver 唯一一道可说的题目? Pogo-Cow Descri ...
- USACO翻译:USACO 2014 MARCH Silver三题
USACO 2014 MARCH 一.题目概览 中文题目名称 农田灌溉 懒牛 牛叫 英文题目名称 irrigation lazy mooomoo 可执行文件名 irrigation lazy mooo ...
- [9018_1592]USACO 2014 Open Silver Fairphoto
题目描述 Farmer John's N cows (1 <= N <= 100,000) are standing at various positions along a long o ...
- [USACO 2012 Mar Silver] Landscaping【Edit Distance】
传送门:http://www.usaco.org/index.php?page=viewproblem2&cpid=126 好题啊好题,一开始就输给了这道题的想法! 先把原始状态以及目标状态换 ...
随机推荐
- Java实现 LeetCode 701 二叉搜索树中的插入操作(遍历树)
701. 二叉搜索树中的插入操作 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树. 返回插入后二叉搜索树的根节点. 保证原始二叉搜索树中不存在新值. 注意,可能存在多种有效的插入 ...
- Java实现 LeetCode 454 四数相加 II
454. 四数相加 II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...
- java中eclipse控制台接受输入的方法
如果是超大字符串的话,相比较来说用io流比较快捷 import java.io.BufferedReader; import java.io.IOException; import java.io.I ...
- java中ThreadLocal类的详细介绍(详解)
ThreadLocal简介 变量值的共享可以使用public static的形式,所有线程都使用同一个变量,如果想实现每一个线程都有自己的共享变量该如何实现呢?JDK中的ThreadLocal类正是为 ...
- mysql基础-数据库初始化操作必要步骤和客户端工具使用-记录(二)
0x01 mysql启动时,读取配置文件的顺序 Default options are read from the following files in the given order:/etc/my ...
- golang连接达梦数据库的一个坑
golang连接达梦数据库的一个坑 有一次项目中用到了达梦数据库,后端语言使用的golang,达梦官方并未适配专门的golang连接方式,正一筹莫展的时候发现达梦提供了odbc的连接,这样可以使用类似 ...
- 实验五 shell脚本编程
项目 内容 这个作业属于哪个课程 课程链接 这个作业的要求在哪里 作业要求 学号-姓名 17041428-朱槐健 作业学习目标 1. 了解shell脚本的概念及使用 2.掌握shell脚本语言的基本语 ...
- MATLAB实例:多元函数拟合(线性与非线性)
MATLAB实例:多元函数拟合(线性与非线性) 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 更多请看:随笔分类 - MATLAB作图 之前写过一篇博 ...
- TensorFlow开发者证书 中文手册
经过一个月的准备,终于通过了TensorFlow的开发者认证,由于官方的中文文档较少,为了方便大家了解这个考试,同时分享自己的备考经验,让大家少踩坑,我整理并制作了这个中文手册,请大家多多指正,有任何 ...
- [CF696D]Legen...
题目 点这里看题目. 分析 首先对于模式串建立 AC 自动机,并且计算出每个状态\(p\)的贡献总和\(con(p)\). 考虑一个朴素的 DP : \(f(i,p)\):当前串长度为 ...