题目大意:给出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. expect交互式自动化脚本

    一 什么是expect 1 Expect is a tool for automating interactive applications such as telnet, ftp, passwd, ...

  2. hdu 3530 Subsequence 单调队列

    题目链接 题目给出n个数, 一个下界m, 一个上界k, 让你求出最长的一段序列, 满足这段序列中的最大的数-最小的数<=k&&>=m, 输出这段长度. 可以维护两个队列, ...

  3. APM代码学习笔记3:执行过程

    以Linux平台ArduPlane为例 \ArduPlane\Plane.cpp 定义Plane类 继承自AP_HAL::HAL::Callbacks ,获取hal对象. \ArduPlane\Ard ...

  4. sqlplus命令手册

    show errorshow allshow usersqlplus show和set命令是两条用于维护SQLPlus系统变量的命令 : SQL> show all --查看所有系统变量值 SQ ...

  5. [转]printf 函数实现的深入剖析

    研究printf的实现,首先来看看printf函数的函数体 int printf(const char *fmt, ...) { int i; char buf[256];          va_l ...

  6. SQL语句的MINUS,INTERSECT和UNION ALL

    SQL语句中的三个关键字:MINUS(减去),INTERSECT(交集)和UNION ALL(并集); 关于集合的概念,中学都应该学过,就不多说了.这三个关键字主要是对数据库的查询结果进行操作,正如其 ...

  7. The Use of Aliases in ElasticSearch

    http://paulsabou.com/blog/2012/04/15/the-use-of-aliases-in-elasticsearch/ https://github.com/taskrab ...

  8. 射频识别技术漫谈(29)——射频接口芯片TRF7960

    TRF7960系列是TI推出的载波为13.56MHz.支持ISO15693.ISO14443A/B和FeliCa协议的射频接口芯片.许多人更关心它能不能读写MF1卡片,就我的理解及实际验证,由于MF1 ...

  9. php socket 超时设置

    1.php创建socket的方法和设置超时的方法,贴出来分享一下 //如果$waitAckSec=0,则返回成功发送的字节�? //如果$waitAckSec大于0,则返回发送后接收到得内容 //任何 ...

  10. Img垂直居中

    IMG垂直居中问题 2011-02-22 10:51:00|  分类: CSS |  标签:垂直居中  div  align  img  vertical  |举报|字号 订阅    转载来自:htt ...