洛谷 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需要的最小需要拍摄的照片数量
输入输出样例
7 3 1 3 2 4 5 6
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; }