整数区间


【题目描述】

一个整数区间[A,B]
请编程完成以下任务:
1.从文件中读取区间的个数及其它们的描述;
2.找到满足下述条件的所含元素个数最少的集合中元素的个数,对于每一个区间,都至少有两个不同的整数属于该集合。


【输入】
首行包括区间的数目n,1<=n<=10000,接下来的n 行,每行包括两个整数a,b,被一空格隔开,0<=a<=b<=10000,它们是某一个区间的开始值和结束值。


【输出】
第一行集合元素的个数,对于每一个区间都至少有两个不同的整数属于该区间,且集合所包含元素数目最少。


样例输入
43
6
2 4
0 2
4 7


样例输出
4

这道题的题目说的很迷,说人话就是求一个集合,使每一个区间在这个集合里面都至少有两个元素,输出集合元素。

一种 O(n ^ 2) 的算法是先开一个标记数组,记录集合的元素取了哪些。然后按区间开始的端点从小到大排序,从后往前找。开始先标记最后一个区间的前两个值,然后每一次循环都遍历该区间的所有数,看看有几个被放到了集合里。若有两个,就进行下一次循环;若一个,就标记区间第一个值,ans++;若没有,就标记区间前两个值,ans += 2。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 
 8 #define rep(i ,a, n) for(int i = a; i <= n; ++i)
 9 #define per(i, n, a) for(int i = n; i >= a; --i)
10 typedef long long ll;
11 const int maxn = 1e4 + 5;
12 
13 struct Node
14 {
15     int sta, end;
16     bool operator < (const Node& other)const
17     {
18         return sta < other.sta;
19     }
20 }a[maxn];
21 int n;
22 int vis[maxn], sum = 0;
23 int main()
24 {
25     freopen("a.in", "r", stdin);
26     freopen("a.out", "w", stdout);
27     scanf("%d", &n);
28     rep(i, 1, n) scanf("%d%d", &a[i].sta, &a[i].end);
29     sort(a + 1, a + n + 1);
30     per(i, n, 1)
31     {
32         int tot = 0;
33         rep(j, a[i].sta, a[i].end) if(vis[j]) tot++;
34         if(tot == 0) {sum += 2; vis[a[i].sta] = vis[a[i].sta + 1] = 1;}
35         else if(tot == 1) {sum++; vis[a[i].sta] = 1;}
36     }
37     printf("%d\n", sum);
38     return 0;
39 }

这个算法为什么成立呢?因为我们每一次取的都是区间的前两个值,这样做就是使所取得这两个值在接下来的区间中的概率最大,从而在后面的查询中尽量少的添加集合中的元素。


我们发现,对于每一次区间的操作,只是都用了区间中的前两个元素。这样就可以开两个变量记录,就不用开数组遍历了。(默认flag1 < flag2)

若区间末尾大于flag2 ,那么就说明这个区间至少有两个数被选进集合中了,过;若在flag1 和 flag2 之间,吧 flag1 变成 flag2,flag1 变成 区间开始值;若小于 flag1 ,flag1 和 flag2 分别变成区间头和头+1.

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 #define rep(i, a, n) for(int i = a; i <= n; ++i)
 8 #define per(i, n, a) for(int i = n; i >= a; --i)
 9 typedef long long ll;
10 const int maxn = 1e4 + 5;
11 
12 struct Node
13 {
14     int sta, end;
15     bool operator < (const Node& other)const
16     {
17         return sta < other.sta;
18     }
19 }a[maxn];
20 int n, flag1, flag2;
21 int ans = 0;
22 int main()
23 {
24     freopen("a.in", "r", stdin);
25     freopen("a.out", "w", stdout);
26     scanf("%d", &n);
27     rep(i, 1, n) scanf("%d%d", &a[i].sta, &a[i].end);
28     sort(a + 1, a + n + 1);
29     flag1 = a[n].sta; flag2 = flag1 + 1; ans += 2;
30     per(i, n - 1, 1)
31     {
32         if(a[i].end < flag1)
33         {
34             flag1 = a[i].sta; flag2 = flag1 + 1;
35             ans += 2;
36         }
37         else if(a[i].end >= flag1 && a[i].end < flag2)
38         {
39             flag2 = flag1; flag1 = a[i].sta;
40             ans++;
41         }
42     }
43     printf("%d\n", ans);
44     return 0;
45 }

优质内容筛选与推荐>>
1、eclipse解决git冲突举例
2、[原创]DebugTools系列(3):AQTime实践
3、xml xmlnamespace
4、Java oop第05章_多态、接口
5、Nunit单元测试演练


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn