HDU 5583 Kingdom of Black and White

Kingdom of Black and White

####Problem Description

In the Kingdom of Black and White (KBW), there are two kinds of frogs: black frog and white frog.
Now N frogs are standing in a line, some of them are black, the others are white. The total strength of those frogs are calculated by dividing the line into minimum parts, each part should still be continuous, and can only contain one kind of frog. Then the strength is the sum of the squared length for each part.
However, an old, evil witch comes, and tells the frogs that she will change the color of at most one frog and thus the strength of those frogs might change.
The frogs wonder the maximum possible strength after the witch finishes her job.

####Input
First line contains an integer T, which indicates the number of test cases.

Every test case only contains a string with length N, including only 0 (representing a black frog) and 1 (representing a white frog).

####Data
for 60% data, 1≤N≤1000.

 	for 100% data, 1≤N≤10^5.⋅1≤T≤50.

	the string only contains 0 and 1.

####Output
For every test case, you should output “Case #x: y”,where x indicates the case number and counts from 1 and y is the answer.

####Sample Input
2
000011
0101

####Sample Output
Case #1: 26
Case #2: 10

####题目大意:
给定一个串仅包含0和1,至多修改串中的一个数,询问该串中相邻相等串长度的平方和

####样例解释:
对于第一个串000011,我们改变5号位的1,变为000001。第一个连续串长度为5,对答案的贡献为25;第二个连续串长度为1,对答案的贡献为1。即:答案 = 25 + 1 = 26。
对于第二个串0101,我们可以改变2号位的1或者三号位的零,那么都会出现一个连续串的长度为3、另一个连续串的长度为1,即:答案为 9 + 1 = 10。

####题解:
每次暴力修改与当前最优值比较,复杂度为n^2,可以过60%的数据。
我们需要一个时间复杂度为O(nlogn)以下的方法,实现如下:
1、记录初始状态下:
(1)连续串的长度以及个数 //数组a和tot;
(2)每个连续串的长度的平方; // 数组num
(3)平方数的前缀和 // 数组sum
2、枚举修改位置,设从i个串中修改,该串的长度减一,则存在以下两个方案:
(1)修改该串第一个元素,第i-1个串长度加一;
(2)修改该串最后一个元素,第i+1个串长度加一。
3、更新答案:
我们不难发现修改第i个串不会影响前i-2个串或后(tot-i-1)个串
即:
(1)改变i中一个元素加到 i -1:前i-2个串不变,a[i -1] + 1 , a[i] - 1 , 后面不变
(2)改变i中一个元素加到 i+1:前i-1个串不变,a[i+1] + 1 , a[i] - 1 , 后面不变
设答案为ans 则:
ans = max ( max ( ans,sum [ tot ] ), // 不做修改
max ( sum[ i - 2 ] + ksm(a[ i ] - 1 , 2 ) + ksm( a [ i-1 ] + 1 , 2 ) + sum[ tot ] - sum [ i ] , // 对应(1)
sum[i-1] + ksm(a[i] - 1,2 ) + ksm ( a[i+1] + 1,2 ) + sum[tot] - sum[i+1] ) ) // 对应(2)
其中ksm(a,b)表示 a ^ b
4、特别的当a [ i ] = 1的时候 ,第i-1个串以及第i+1个串会与第i个串都连接起来,其余不变。
即:ans = max ( max ( ans , sum [ tot ] ) ,//不做修改
sum[ i - 2 ] + sum [ tot ] - sum [ i + 1 ] + ksm ( a[ i ] + a[ i - 1 ] + a[ i + 1 ] , 2 ) ) ;//修改
5、特别的当只有一个串的时候,不论如何修改都会减小答案,所以原串长度的平方即为答案。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll ans,num[maxn],sum[maxn],t,len,tot,a[maxn];
char s[maxn];
ll max(ll a,ll b)
{
	if(a > b) return a;
	return b;
}
ll ksm(int a,int b)
{
	if(a == 0) return 0;
	else if(a == 1 || b == 0) return 1;
	else if(b == 1) return a;
	else if(b % 2 == 0) return ksm(a,b/2) * ksm(a,b/2);
	else if(b % 2 == 1) return ksm(a,b/2) * ksm(a,b/2) * a;	
}
int main()
{
	int cnt = 1;
	scanf("%I64d",&t);
	while(t --)
	{
		memset(a,0,sizeof(a));
		memset(num,0,sizeof(num));
		memset(sum,0,sizeof(sum));
		ans = 0;
		tot = 1;
		a[1] = 1;
		scanf("%s",s);
		len = strlen(s);
		for(int i = 1;i < len;i ++)
		{
			if(s[i] == s[i-1]) a[tot] ++;
			else tot += 1,a[tot] = 1;
		} 
		for(int i = 1;i <= tot;i ++)
		{
			num[i] = ksm(a[i],2);
			sum[i] = sum[i-1] + num[i];
		}
		sum[tot + 1] = sum[tot];
		for(int i = 1;i <= tot;i ++)
		{
			if(a[i] != 1)
			ans = max(max(ans,sum[tot]),max(sum[i-2] + ksm(a[i] - 1,2) + ksm(a[i-1] + 1,2) + sum[tot] - sum[i],sum[i-1] + ksm(a[i] - 1,2) + ksm(a[i+1] + 1,2) + sum[tot] - sum[i+1]));
			if(a[i] == 1) ans = max(max(ans,sum[tot]),sum[i-2] + sum[tot] - sum[i+1] + ksm(a[i]+a[i-1]+a[i+1],2));
		}
		if(tot == 1) ans = ksm(a[tot],2) ;
		printf("Case #%d: %I64d\n",cnt,ans);
		cnt ++;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值