• 洛谷 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;
    }
    


  • 相关阅读:
    ConcurrentHashMap的初步使用场景、源码分析讲解(中)
    ConcurrentHashMap的初步使用场景、源码分析讲解(上)
    CyclicBarrier用例、源码分析讲解
    Semaphore用例、源码分析讲解
    CountDownLatch用例、源码分析讲解
    Condition用例、源码分析详解(下)
    Condition用例、源码分析详解(上)
    图解数据结构之数组、链表、栈、队列
    Python--day27--复习
    Python--day26--反射
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6537731.html
Copyright © 2020-2023  润新知