小小粉丝度度熊
Problem Description
度度熊喜欢着喵哈哈村的大明星——星星小姐。
为什么度度熊会喜欢星星小姐呢?
首先星星小姐笑起来非常动人,其次星星小姐唱歌也非常好听。
但这都不是最重要的,最重要的是,星星小姐拍的一手好代码!
于是度度熊关注了星星小姐的贴吧。
一开始度度熊决定每天都在星星小姐的贴吧里面签到。
但是度度熊是一个非常健忘的孩子,总有那么几天,度度熊忘记签到,于是就断掉了他的连续签到。
不过度度熊并不是非常悲伤,因为他有m张补签卡,每一张补签卡可以使得某一忘签到的天,变成签到的状态。
那么问题来了,在使用最多m张补签卡的情况下,度度熊最多连续签到多少天呢?
Input
本题包含若干组测试数据。
第一行两个整数n,m,表示有n个区间,这n个区间内的天数,度度熊都签到了;m表示m张补签卡。
接下来n行,每行两个整数(l[i],r[i]),表示度度熊从第l[i]天到第r[i]天,都进行了签到操作。
数据范围:
1<=n<=100000
0<=m<=1000000000 0<=l[i]<=r[i]<=1000000000
注意,区间可能存在交叉的情况。
Output
输出度度熊最多连续签到多少天。
Sample Input
2 1 1 1 3 3 1 2 1 1
Sample Output
3 3
Hint
样例一:度度熊补签第2天,然后第1天、第二天和第三天都进行了签到操作。
样例二:度度熊补签第2天和第3天。
———————————————————————————————
这道题读入后要先初始化一波 使得相邻块之间没有交点
这道题维护两个指针 l r
l 维护是当前的左端点 r是右端点
r先向右走 如果cost超过m就挪左端点就好了
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=100007; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } int n,m,cnt,nl,nr,ans,sum; struct node{ int l,r; bool operator<(const node &x)const{return l<x.l;} }e[M],q[M]; int cal(int x){return x?q[x].l-q[x-1].r:0;} int main() { while(scanf("%d %d",&n,&m)==2){ for(int i=0;i<n;i++) e[i].l=read(),e[i].r=read()+1; sort(e,e+n); cnt=0; int ll=e[0].l,rr=e[0].r; for(int i=1;i<n;i++){ if(e[i].r<=rr) continue; if(e[i].l<=rr) rr=e[i].r; else q[++cnt]=(node){ll,rr},ll=e[i].l,rr=e[i].r; } q[++cnt]=(node){ll,rr}; ans=0; for(int i=0,j=0,cost=0;i<=cnt;i++){ int s=q[i].r-q[j].l; cost+=cal(i); while(cost>m){ j++; s=q[i].r-q[j].l; cost-=cal(j); } ans=max(ans,s-cost+m); }printf("%d\n",ans); } return 0; }
时间: 2024-10-11 22:17:24