• 整数区间


    【题目描述】

    一个整数区间[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
    ", 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
    ", ans);
    44     return 0;
    45 }
  • 相关阅读:
    关于webpack的cdn配置
    谁都能听懂的Redux+Redux-Saga超级傻瓜教程
    记一个react拖动排序中的坑:key
    es6 解构写法:给变量取别名
    C++新型强制类型转换。
    C++ new、delete、namespace关键字。
    C++ 调用C语言、extern "C"、__cplusplus关键字
    C++ 重载函数
    liunx 环境下安装 Eclipse C++
    C++ 内联函数 inline关键字
  • 原文地址:https://www.cnblogs.com/mrclr/p/8584685.html
走看看 - 开发者的网上家园