MAX 的读书计划(贪心)

问题 E: MAX 的读书计划

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
MAX 很喜欢读书,为了安排自己的读书计划,他会预先把要读的内容做好标记,A B 表示一个页段,即第 A 到 B 面,当然 A<B,若有两个页段 A-B,B-C,则可以直接记为 A-C,这样,他就可以一次看完,现在告诉你 n 个页段,请你帮他求出最长的一条页段,并输出这条页段的长度和组成它的页段个数。举个例子:
有 6 个页段:
2-7 1-3 3-12 12-20 7-10 4-50
那么连续的页段就有:
1-3,3-12,12-20 长度为 20-1+1=20 由 3 个页段组成
2-7,7-10 长度为 10-2+1=9 由 2 个页段组成
4-50 长度为 50-4+1=47 由 1 个页段组成
那么最长的一条就是第三个,所以结果为 47 1。
需要注意的是:如果有两条不一样的连续的页段长度同时为最大,那么取组成页段数多的一条.
例子: 1-5,5-10,1-10
输出: 10 2
输入
第一行为一个整数n,n<500;
第二行到第n+1行,每行两个整数A,B,记录一个页段的信息。0<=A<B<500
输出
输出一个整数,即最长的页段的长度和组成它的页段数。
样例输入 Copy
7
1 5
10 12
3 10
2 7
2 10
12 16
7 9
样例输出 Copy
15 3
提示
1-5 长度为5由1个页段组成
3-10,10-12,12-16 长度为14由3个页段组成
2-7,7-9 长度为8由2个页段组成
2-10,10-12,12-16 长度为15由3个页段组成

所以输出最长的页段的长度即15由3个页段组成

【数据规模】
对于30%的数据n<20,0<=A<B<500
对于100%的数据n<500,0<=A<B<500

  • 思路:两个点如果不能直接连通的话需要在她直接找到一个点连通 这个点与第一个点,在联通这个点跟后一个点,所以我们就要在连接点上来看了。先设二维数组,存放长度,且存在。然后就是判断了,如果两点之间有连接点,则判断前一点是否可由他这之前的到达,如果能,判断长度与原本的大小,大则赋值 并标记下来连接点,不能到到直接比较他遇到当前的长度大小。
  • 然后找到最长。然后找桥梁最多的。

代码:

#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
using namespace std;
const int maxn=2e5+1010;
#define inf 0x3f3f3f3f
const int mod=1e9+7;
const int MOD=10007;
 
inline int read() {
    int x=0;
    bool t=false;
    char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
 
priority_queue<ll , vector<ll> , greater<ll> > mn;//上  小根堆        小到大 
priority_queue<ll , vector<ll> , less<ll> > mx;//下    大根堆     大到小
map<ll,ll>mp;
 
ll n,m,t,l,r,p;
ll sum,ans,res,cnt,flag
,maxx,minn;
bool isprime[maxn];
ll a[maxn],b[maxn],c[maxn];
ll dis[maxn],vis[maxn];
ll dp[1010][1010];
string str,s;
 
struct king {
    ll id;
    string str;
}q[maxn];
bool cmp(king a,king b){
    if(a.id!=b.id) return a.id>b.id;
    else return a.str<b.str;
}
ll qpow(ll a,ll b){
    ll sum=1;
    while(b){
        if(b&1) sum=sum*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return sum;
}
 
 
int main(){
    cin>>n;
    for(int i=1;i<=n;i ++)
    {
        scanf("%lld%lld",&l,&r);
        dp[l][r]=r-l+1;
        maxx=max(maxx,r);
    }
    for(int i=0;i<=maxx;i++){
        for(int j=0;j<i;j++){
            if(dp[j][i]){//存在  
                if(dis[j]){
                    if(dis[i]<dis[j]+dp[j][i]){
                        dis[i]=dis[j]+dp[j][i]-1;//最大长度 
                        vis[i]=j;//这个的中间连接点是j 也就是前一个点 
                     }
                 }else {//这个连接点不存在 直接用 新的一个点做根 
                    dis[i]=max(dis[i],dp[j][i]);
                 }
             }
         }
     }
     for(int i=0;i<=maxx;i++)
     {
        if(dis[i]>minn)
            minn=dis[i];//找到最长的 
     }
     sum=1;
     for(int i=0;i<=maxx;i++){
        if(dis[i]==minn){
            l=1,r=i;
            while(vis[r]!=0){//由最后一点 向前找 
                l++;
                r=vis[r];
             }
            sum=max(sum,l);
         }
     }
     cout<<minn<<" "<<sum<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值