CodeForces 1000B Light It Up

28 篇文章 0 订阅
题目:点击打开链接
题意:有一盏灯,0时刻开着。n次操作,你可以在其中加入一次操作(或者不加),操作为:a[i]时刻按一下开关,状态变为相反状态(开->关or关->开)。问灯亮着的时长最长为多少? 
保证a[i-1]<a[i]。 
3 10 
4 5 7 
0~4开(时长为4-0),4~6关(时长为6-4),6~7开(时长为7-5),7~10关(时长为10-7) 
我们可以在第3个时刻操作一下开关,过程变为:0~3开(时长为3-0),3~4关(时长为4-0),4~6开(时长为6-4),5~7关(时长为7-5),7~10开(时长为10-7),3+2+3=8
分析:我们加一次操作相当于把某个数字拆成两个,肯定为一开一关,我们肯定让改变的这个区间长度开灯时间尽可能长,操作之后的开灯时长为:该数字之前的总开灯时长+该数字之后的总关灯时长+本区间改变之后的开灯时长。 记录到第i次操作时亮灯时长记为b[i]。如果本区间为开灯状态且区间长度大于1,则操作后开灯时长为:b[i]+m-a[i]-(b[n+1]-b[i])-1,如果本区间本来为关灯状态且区间长度大于1,则则操作后开灯时长为:b[i]+a[i]-a[i-1]-1+m-a[i]-(b[n+1]-b[i]),所以遍历一遍维护最大值即可。另外可以不操作,此时开灯时长为b[n+1]。

代码:

#pragma comment(linker, "/STACK:102400000,102400000")///手动扩栈
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define MOD 1000000007
#define PI acos(-1.0)
const int N = 1e6+10;

ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

int n,m,a[N],b[N];

int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    int f=1;
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        b[i]=b[i-1]+f*(a[i]-a[i-1]);
        f=1-f;
    }
    a[n+1]=m;
    b[n+1]=b[n]+f*(m-a[n]);
    int ans=b[n+1];
    for(int i=1;i<=n+1;i++) {
        if(a[i]-a[i-1]>1) {
            if(i&1) ans=max(ans,b[i]-1+m-a[i]-(b[n+1]-b[i]));
            else ans=max(ans,b[i]+a[i]-a[i-1]-1+m-a[i]-(b[n+1]-b[i]));
        }
    }
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值