题目大意:给出N个区间[Li,Ri](1<=i<=N),一个正整数M,求N个区间里,并区间包含[0,M]的区间的最小个数(无解时输出:No solution)。

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

数据规模:1<=M<=5000,-50000<=Li<Ri<=50000,1<=N<=99999。

理论基础:无。

题目分析:用贪心法。

首先,预处理,除去所有可以被别的区间包含的区间,可以证明,这样以后,得出的最优解不会劣于未处理前。

证明:假设原解用到区间[a,b]包含于[m,n]那么将原解中的区间替换为[m,n]答案不会变劣,证毕。

还可以证明,在所有能够覆盖左端点的区间中选择最靠近左端点的区间得到的解不会劣于原解。

证明:假设原解中有区间[a,b],现有区间[m,n],a<m由预处理知,各区间互不包含所以b<n,那么[a,b]覆盖的区域,[m,n]也可以将其覆盖,因为[m,n]也可以覆盖左端点,而n>b,所以必然也可以覆盖右端点,这样结果不劣于原解。所以命题得证。

贪心策略:每次找到一个区间后,将左端点更新为此区间的右端点,再进行寻找。直到找到的区间的右端点覆盖了M为止。

最后,我们来证明这样贪心得出的解必为最优解,假设不是最优解,那么必然有一个区间可以去除。

1.假设此区间为第一个区间,则根据贪心策略,有第二个区间不覆盖左端点(如果覆盖的话,选择的第一个区间即为此区间),去掉第一个区间后,则左端点没有被覆盖,所以此区间不可去除。

2.假设此区间为最后一个区间,同1,如果去除此区间后,则右端点未被覆盖,所以不可去除。

3.假设此区间为相邻的三个区间[a,b],[x,y],[m,n]中的[x,y]。则根据贪心策略存在d属于区间[x,y]有:a<x<b<m<y<n,如果去掉[x,y],则区间[b,m]未被覆盖,所以不可去除。

综上所述,贪心策略所得解中所有区间都不可去除,所以必为最优解。得证。

代码如下:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<ctime>
#include<vector>
using namespace std;
typedef double db;
#define DBG 0
#define maa (1<<31)
#define mii ((1<<31)-1)
#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); } //调试
#define dout DBG && cout << __LINE__ << ">>| "
#define pr(x) #x"=" << (x) << " | "
#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl
#define pra(arr, a, b) if(DBG) {\
dout<<#arr"[] |" <<endl; \
for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \
if((b-a+1)%8) puts("");\
}
template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }
template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }
typedef long long LL;
typedef long unsigned int LU;
typedef long long unsigned int LLU;
#define N 100000
pair <int,int> s[N+5],pre[N+5],ans[N+5];
int m,cnt,np,na;
ostream& operator << (ostream& out,pair <int,int> a)
{
printf("%d %d\n",a.first,a.second);
return out;
}
bool fun(pair <int,int> a,pair <int,int> b)
{
if(a.first!=b.first)return a.first<b.first;
else return a.second<b.second;
}
void solve()
{
int left=0,right=m,now=0;
while(now<=np&&left<right)
{
while(now<=np&&pre[now].first<=left)now++;
if(now==0)break;
if(pre[now-1].first<=left)
{
ans[na++]=pre[now-1];
left=pre[now-1].second;
}
}
if(left>=right)
{
printf("%d\n",na);
for(int i=0;i<na;i++)cout<<ans[i];
}
else printf("No solution\n");
}
int main()
{
scanf("%d",&m);
while(1)
{
int a,b;
scanf("%d%d",&a,&b);
if(a!=0||b!=0)
{
s[cnt].first=a;
s[cnt++].second=b;
}
else break;
}
sort(s,s+cnt,fun);
pra(s,0,cnt-1)
pre[0]=s[0];
for(int i=1;i<cnt;i++)
{
if(s[i].first==pre[np].first)pre[np]=s[i];
else if(s[i].second<=pre[np].second);
else pre[++np]=s[i];
}
pra(pre,0,np)
solve();
return 0;
}

其中,ans[i]即为用来存储所选区间的数组。

by:Jsun_moon http://blog.csdn.net/Jsun_moon

URAL 1303的更多相关文章

  1. 贪心 URAL 1303 Minimal Coverage

    题目传送门 /* 题意:最少需要多少条线段能覆盖[0, m]的长度 贪心:首先忽略被其他线段完全覆盖的线段,因为选取更长的更优 接着就是从p=0开始,以p点为标志,选取 (node[i].l < ...

  2. URAL 1303 Minimal Coverage

    URAL 1303 思路: dp+贪心,然后记录路径 mx[i]表示从i开始最大可以到的位置 sufmx[i]表从1-i的某个位置开始最大可以到达的位置 比普通的贪心效率要高很多 代码: #inclu ...

  3. ural 1303 Minimal Coverage【贪心】

    链接: http://acm.timus.ru/problem.aspx?space=1&num=1303 http://acm.hust.edu.cn/vjudge/contest/view ...

  4. Ural 1303 Minimal Coverage(贪心)

    题目地址:Ural 1303 先按每一个线段的左端点排序,然后设置一个起点s.每次都从起点小于等于s的线段中找到一个右端点最大的. 并将该右端点作为新的起点s,然后继续找. 从左到右扫描一遍就可以. ...

  5. ural 1303 Minimal Coverage(贪心)

    链接: http://acm.timus.ru/problem.aspx?space=1&num=1303 按照贪心的思想,每次找到覆盖要求区间左端点时,右端点最大的线段,然后把要求覆盖的区间 ...

  6. URAL 1303. Minimal Coverage(DP)

    题目链接 又是输出路径...这题完全受上题影响,感觉两个题差不多..用了基本上一样的算法写了,这题比较纠结,就是卡内存啊...5000*5000的数组开不了..然后没办法,水了好几次MLE,看了一下虎 ...

  7. URAL DP第一发

    列表: URAL 1225 Flags URAL 1009 K-based Numbers URAL 1119 Metro URAL 1146 Maximum Sum URAL 1203 Scient ...

  8. Contest 7.21(贪心专练)

    这一次都主要是贪心练习 练习地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview Problem APOJ 13 ...

  9. [置顶] 2013_CSUST暑假训练总结

    2013-7-19 shu 新生训练赛:母函数[转换成了背包做的] shuacm 题目:http://acm.hdu.edu.cn/diy/contest_show.php?cid=20083总结:h ...

随机推荐

  1. Hadoop学习之HBase和Hive的区别

    Hive是为简化编写MapReduce程序而生的,使用MapReduce做过数据分析的人都知道,很多分析程序除业务逻辑不同外,程序流程基本一样.在这种情况下,就需要Hive这样的用户编程接口.Hive ...

  2. 以Android环境为例的多线程学习笔记(二)-----------------锁和条件机制

    现在的绝大多数应用程序都是多线程的程序,而当有两个或两个以上的线程需要对同一数据进行存取时,就会出现条件竞争,也即 是这几个线程中都会有一段修改该数据状态的代码.但是如果这些线程的运行顺序推行不当的话 ...

  3. Java中的流程控制(三)

    关于Java中的流程控制 关于Java中的流程控制 4.do while语句 do while语句的功能和while语句差不多,只不过它是在执行完第一次循环后才检测条件表达式的值,这意味着包含在大括号 ...

  4. SQL 处理空值

    问题: 在数据库中经常会有为null和''的值的列,在查询的时候,我们需要将它们转化成有效的值. 解决方案: 在emp表中的comm注释有的为null有的为'',在查询的时候 我们希望没有注释的显示为 ...

  5. hdu 2824The Euler function

    题目链接 快速求出a到b之间所有数的欧拉函数. 一个一个求肯定是不行的, 我们知道欧拉函数的公式为phi(n) = n*(1-1/i1)*(1-1/i2).......i1, i2为素因子. 那么我们 ...

  6. [问题解决] File "/struts-tags" not found

    错误:org.apache.jasper.JasperException: File "/struts-tags" not found 发生场景:tomcat服务器 解决方案:将t ...

  7. 完美解决CTRL+空格不能切换中/英文输入法的问题

    首先任务栏上的输入法图标上点右键选择设置. 然后选择键设置,双击第一个“在不同的输入语言之间切换”先勾选“切换输入语言”下面选择左手ALT.取消右边“切换键盘布局”前的勾. 然后进入“中文(简体)输入 ...

  8. java selenium webdriver实战 seleniumIDE

    Selenium是ThoughtWorks公司,一个名为Jason Huggins的测试为了减少手工测试的工作量,自己实现的一套基于Javascript语言的代码库 使用这套库可以进行页面的交互操作, ...

  9. ThinkPHP 3 的输出

    一.ThinkPHP 3 的输出 (重点) a.通过 echo 等PHP原生的输出方式在页面中输出 b.通过display方法输出 想分配变量可以使用assign方法 c.修改左右定界符 休要修改配置 ...

  10. button 变成圆

      btn.layer.cornerRdius = width/2.0;btn.layer.maskToBounds = width/2.0: