Codeforces 1000B Light It Up(思维)
Posted kaleidoscope233
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1000B Light It Up(思维)相关的知识,希望对你有一定的参考价值。
题目大意:有一盏灯,在0时刻亮起,M时刻关闭。在一些时刻有一些开关可以改变灯的状态(开-->关,关-->开)。给你一个机会再0~m任何一个时刻(不与a[i]相同)加一个开关,求灯亮着的最大时间。
显然应该把这个开关安排在任何一个a[i]的相邻位置(左边或右边),这样浪费的时间会最少。然而无论在左边还是右边,两个情况都是同一个道理,所以我们只需要考虑放在a[i]左边相邻的一种情况。
这题的妙处就是:无论在哪添加这个开关,每个开关对于改变灯的状态都会改变。
Eg:如果这个开关原本会把灯关掉,那么添加开关后它会让灯亮。
我们处理一个b[i]前缀和数组,表示a[i]时刻前灯亮的时间;c[i]前缀和数组表示a[i]时刻后灯关着的时间;
那么当把灯放在a[i]-1时刻时,只会影响a[i]前面灯亮着的时间少了1,而后面亮着的时间再此时由未添加开关时的b[n]-b[i]变成了c[n]-c[i] (因为a[i]后每个开关对于改变灯的状态改变,关--开);
m可以看做一个时刻算到b[n+1],c[n+1]中,所以在a[i]-1处添加开关的贡献是b[i]-1+c[n+1]-c[i],扫一遍维护最大值。
由于可以不加开关,还要将答案与不加开关的时间比较。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <queue> 6 #define ll long long 7 #define out(a) printf("%d ",a) 8 using namespace std; 9 int n,m; 10 int a[100050],b[100050],c[100050]; 11 int now,ans,sum; 12 int read() 13 { 14 int s=0,t=1; char c; 15 while (c<‘0‘||c>‘9‘){if (c==‘-‘) t=-1; c=getchar();} 16 while (c>=‘0‘&&c<=‘9‘){s=s*10+c-‘0‘; c=getchar();} 17 return s*t; 18 } 19 int main() 20 { 21 n=read(); m=read(); ans=-2333333; 22 for (int i=1;i<=n;i++){ 23 a[i]=read(); b[i]=b[i-1]; c[i]=c[i-1]; 24 if (i&1) b[i]+=a[i]-a[i-1],sum+=a[i]-a[i-1]; 25 else c[i]+=a[i]-a[i-1]; 26 } 27 if (n&1) b[n+1]=b[n],c[n+1]=c[n]+m-a[n]; 28 else b[n+1]=b[n]+m-a[n],c[n+1]=c[n],sum+=m-a[n]; 29 for (int i=1;i<=n+1;i++) 30 now=b[i]+c[n+1]-c[i]-1,ans=max(now,ans); 31 ans=max(ans,sum); 32 out(ans); 33 return 0; 34 }
以上是关于Codeforces 1000B Light It Up(思维)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces - 1610A Anti Light‘s Cell Guessing