题目描述:
众所周知,ZJM 住在 B 站。
这一天 Q 老师来找 ZJM 玩,ZJM 决定向 Q 老师展现一下自己快速看番的本领。
ZJM 让 Q 老师任意挑选了一部番,Q老师一眼看中了《辉夜大小姐想让我告白》,已知这部番一共有 N 个精彩片段,每个精彩片段用 [L[i], R[i]] 来表示。
ZJM 从第一分钟开始看,每次可以按下快进键,快进 X 分钟,问 ZJM 最快需要多久可以看完这部番。
Input
第一行给出两个整数 N、X(1 ≤ N ≤ 50, 1 ≤ X ≤ 1e5)
接下来 N 行,每行给出两个整数,L[i]、R[i](1 ≤ L[i] ≤ R[i] ≤ 1e5)
数据保证,R[i-1] < L[i]
Output
输出一个整数,表示 ZJM 最快看完这部番的时间。
Examples
Input
2 3
5 6
10 12
Output
6
Input
1 1
1 100000
Output
100000
Note
在第一个样例中,ZJM 从第 1 分钟开始看,由于 [1, 3] 区间内没有精彩片段,因此 ZJM 快进到了第 4 分钟。
观看完 [4, 6] 区间的内容后,时间来到了第 7 分钟,由于 [7, 9] 区间内没有精彩片段,因此 ZJM 快进到了第 10 分钟,观看完 [10, 12] 区间的内容后,看番结束。
一共耗时 3 + 3 = 6 分钟。
题目分析:
这是一个贪心问题,首先我们要找出有可能进行快进的区间,可以用一个布尔数组表示,在精彩区间内都设置为1表示不能快进,其余的0就表示可以快进,当然这里已经表明精彩内容是有序的,所以不用排序,不过不排序也无妨,本题对精彩内容的出现顺序无关。
for(int i=1;i<=n;i++)
{
cin>>t[i].l>>t[i].r;
for(int j=t[i].l;j<=t[i].r;j++)
{
view[j]=true;
}
}
然后就是看能不能快进的问题了,我一开始做题的时候想错了,是按照x长度的区间从前往后每x个长度进行扫描,后来发现并不是这样的,比如如果每次快进5分钟,第一次精彩时间是1-3分钟,按照我一开始的算法是扫描1-5,6-10…这些区间,实际上不是的,直接从第4分钟就可以扫描了。那这样我们就需要记录下非精彩时间的区间长度,当然区间不止一个,所以我们需要记录下各个区间的长度,这里要注意移动到下一个区间计数的条件是前一个结点在精彩时间,下一个结点就不在精彩区间了,也就是说连续的精彩区间我们是不管的。
for(int i=1;i<=t[n].r;i++)
{
if(view[i]==false)
{
a[count]++;
}
else if(view[i]==true&&view[i+1]==false)
{
count++;
}
}
然后就可以用总的时间减去快进的时间了,这样在能快进区间内的时间能快进就快进,如果时长小于快进时间的话就不快进。
int total=t[n].r;
for(int i=1;i<count;i++)
{
if(a[i]>=x)
{
total=total-x*(a[i]/x);
}
}
cout<<total;
代码如下:
#include<iostream>
using namespace std;
struct time
{
int l;
int r;
}t[100010];
bool view[100010]={0};
int a[100010]={0};
int main()
{
int n,x;
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>t[i].l>>t[i].r;
for(int j=t[i].l;j<=t[i].r;j++)
{
view[j]=true;
}
}
int count=1;
for(int i=1;i<=t[n].r;i++)
{
if(view[i]==false)
{
a[count]++;
}
else if(view[i]==true&&view[i+1]==false)
{
count++;
}
}
int total=t[n].r;
for(int i=1;i<count;i++)
{
if(a[i]>=x)
{
total=total-x*(a[i]/x);
}
}
cout<<total;
}