目录
题目
Thanh 想在一面被均分为 N 段的墙上画一幅精美的壁画。
每段墙面都有一个美观评分,这表示它的美观程度(如果它的上面有画的话)。
不幸的是,由于洪水泛滥,墙体开始崩溃,所以他需要加快他的作画进度!
每天 Thanh 可以绘制一段墙体。
在第一天,他可以自由的选择任意一段墙面进行绘制。
在接下来的每一天,他只能选择与绘制完成的墙面相邻的墙段进行作画,因为他不想分开壁画。
在每天结束时,一段未被涂颜料的墙将被摧毁(Thanh 使用的是防水涂料,因此涂漆的部分不能被破坏),且被毁掉的墙段一定只与一段还未被毁掉的墙面相邻。
Thanh 的壁画的总体美观程度将等于他作画的所有墙段的美观评分的总和。
Thanh想要保证,无论墙壁是如何被摧毁的,他都可以达到至少 B 的美观总分。
请问他能够保证达到的美观总分 B 的最大值是多少。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据的第一行包含整数 N。
第二行包含一个长度为 N 的字符串,字符串由数字 0∼9 构成,第 i 个字符表示第 i 段墙面被上色后能达到的美观评分。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为
Case #x: y
,其中 x 为组别编号(从 1 开始),y 为 Thanh 可以保证达到的美观评分的最大值。数据范围
1≤T≤100,
存在一个测试点N=5∗10^6,其他测试点均满足2≤N≤100输入样例:
4 4 1332 4 9583 3 616 10 1029384756
输出样例:
Case #1: 6 Case #2: 14 Case #3: 7 Case #4: 31
样例解释
在第一个样例中,无论墙壁如何被破坏,Thanh都可以获得 66 分的美观总分。在第一天,他可以随便选一个美观评分3的墙段进行绘画。在一天结束时,第一部分或第四部分将被摧毁,但无论哪一部分都无关紧要。在第二天,他都可以在另一段美观评分 33 的墙段上作画。
在第二个样例中,Thanh 在第一天选择最左边的美观评分为 99 的墙段上作画。在第一天结束时唯一可以被毁掉的墙体是最右边的那段墙体,因为最左边的墙壁被涂上了颜料。在第二天,他可以选择在左数第二段评分为 55 的墙面上作画。然后右数第二段墙体被摧毁。请注意,在第二天,Thanh不能选择绘制第三段墙面,因为它不与任何其他作画墙面相邻。这样可以获得 1414 分的美观总分。
思路
由题意,只能挨着画过的墙壁作画,因此作画的墙壁一定是连续的,那么这段连续的长度是多少呢?因此首先,我们需要判断最后的时候有多少块墙壁能够被作画?
使用 × 表示被摧毁, √ 表示被作画。那么每天的过程就是 √ × √ × √ × √ × ...
那么至少有 块可以被用来作画。
那如果 n 是奇数,在每天作画和摧毁交替中使用过的墙壁总个数一直是保持偶数的。那么最后一块墙壁一定是被用来作画的,作完画后,没有墙壁可以被摧毁。因此,能够被作画的墙壁的个数为 。
那么最后的形式一定是,中间连续一段被作画,两边的墙壁全被毁掉了。
再来思考,是否所有的 长度的区间都是能被画出来的?
由题意可知,被毁掉的墙段一定只与一段还未被毁掉的墙面相邻,说明墙壁只能从两边开始被毁掉。
如下图所示,假设两边销毁的长度分被是a,b,(中间暂且不论,中间 ),那么
。那么中间也同样能划分出两边相同长度的数量(如果是奇数的话,中间还会剩余一个墙壁),那么我们能否证明在无论什么情况下,都能划分
个连续长度。
那我们做出行为:如果第一天销毁左边的墙壁,那么第二天我们就往左边作一幅画,同理右边。
分情况讨论
如果 n 是 奇数,根据上述分析,我们第一天先选择将中间多的剩余的点进行作画。后续在依次做出上述行为,那我们可以在任意时刻保证左边被销毁的长度等于左边被作画的长度(除开中间剩余的点),同理右边,最后结果就如上图所示。那么被作画的长度就为 。
如果 n 是 偶数,第一天我们随机选取一个墙壁作画,比如我们在 与
交界处中选一个点,
的长度变为
,那么左边的长度就为
,右边的长度为
。然后做出上述行为,可以保证右边可以划分
个墙壁来作画,左边一定可以划分出
,即
(不一定能划分到a个,因为在随机选取一个作画后,是先毁掉墙壁),所以能取到
个。
代码
代码没什么看的,这个题主要难在思维
import java.io.*;
class Main{
static int N = 5000010;
static int t;
static int[] a = new int[N];
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
t = Integer.parseInt(in.readLine());
for(int z=1;z<=t;z++){
int n = Integer.parseInt(in.readLine());
String s = in.readLine();
for(int i=1;i<=n;i++){
a[i] = a[i-1]+Integer.parseInt(String.valueOf(s.charAt(i-1)));
}
int res = 0;
int l = n%2==0?n/2:n/2+1;
for(int i=l;i<=n;i++){
int j = i-l+1;
res = Math.max(a[i]-a[j-1],res);
}
out.write("Case #"+z+": "+ res+"\n");
}
out.close();
}
}