洛谷 USACO P2207 Photo

P2207 Photo

题目描述

Framer Jhon 打算给他的N头奶牛照相,( 2 <= N <= 1 000 000 000) 。

他们排成一条线,并且依次取1~N作为编号。

每一张照片可以拍摄到这列奶牛中一个连续的区间中的奶牛。

对于每一头奶牛,FJ都想要让Ta至少出现在一张照片里。

不幸的是,有K对关系不好的奶牛( 1 <= K <= 1000),他们拒绝出现在同一张照片里。

已知所有关系不好的奶牛所在的位置,请计算出FJ需要的最小需要拍摄的照片数量。

输入输出格式

输入格式:

*第一行: 两个整数: N,K.

*第2..K+1行中,第i+1行有两个整数,记为A_i与B_i。它们代表着处在队列中第A_i头奶牛与第B_i头奶牛是关系不好的,它们不能出现在同一张照片里。

输出格式:

*一个整数,代表FJ需要的最小需要拍摄的照片数量

输入输出样例

输入样例#1:
7 3
1 3
2 4
5 6
输出样例#1:
3

说明

输出解释:FJ可以只拍三张照片:[1,2] , [3,5] , [6,7]


网上找不到题解的任何行踪。。

A了这道题之后看了看洛谷上其他提交的代码    都没有我的好


我的代码也不一定完全对,有一些贪心的成分在里面


大概说一下:

每一对无法共存的关系储存在结构体num里,较小的为a,较大的为b。这个问题就转换成了求最少区间不包含任何一个完整的num区间。

我们按照较小的a对num进行排序。


我们逐个扫描每个num,记录当前所在分组的区间[l,r],初始为[1,num[i].b]


这些num区间有三种情况:相交,相离,内含。因此我们需要对这三种情况进行处理。


那么我们很容易发现,只需要保证区间[l,r]只有同一个num中的a而没有b,


所以,根据上述原则,我们:

当前区间为[l,r],扫描到了第i个num

对于相离:此时应该另起炉灶重新划分区间。

因为num[i].a无论如何也加不进我们的当前区间了。我们新区间就是num[i]的[a,b-1],num[1..i].a都已经包含在上一个区间了,还会剩下一些num[1..i].b放在新区间,或者新区间与旧区间的间隔处(间隔处可以随意归给任意区间,不影响划分),而这些b由于a始终不可能被纳入新区间不要理会。但是,当我们扫描到最后一个区间时,需要给这些b单独划分一个区间,需要对最终分组数+ 1。也存在最有一个区间包含所有b的情况,不需要分组数+1,因此需要特判最后的b是不是最大的b(我写题解的时候才想到,我没有写进去,数据太水辣)。分组数ans加一。


对于相交或者内含:把r设置为min(b - 1, b)即可。因为r如果b不是已经扫描过的num中最小的,就一定有一个最小的包含在区间里,不符合设定。


这样,最终答案为ans + 2,因为最开始一个区间没有记录,最后面的b可能没有被包含进来(正如前面所说需要特判,但是数据太水,我没特判)


根据上述分析,我们发现:l根本用不到!!!只需要考虑r即可


上代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

long long n;
int k;
struct T
{
	int a,b;
}num[1000 + 10];
bool cmp(T q, T w){ return q.a < w.a;}
int ans;

int main()
{
	freopen("data.txt", "r", stdin);
	scanf("%d%d", &n, &k);
	for(int i = 1;i <= k;i ++)
	{
		int temp,tempp;
		scanf("%d%d", &temp, &tempp);
		num[i].a = std::min(temp,tempp);
		num[i].b = std::max(temp,tempp);
	}
	std::sort(num + 1,num + 1 + k, cmp);
	int r = num[1].b - 1;
	for(int i = 1; i <= k; i ++)
	{

		if(num[i].a > r)
		{
			ans ++;
			r = num[i].b - 1;
		}
		r = std::min(r, num[i].b - 1);
	}
	printf("%d", ans + 2);
	return 0;
}


转载于:https://www.cnblogs.com/huibixiaoxing/p/6537731.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值