D. Problem with Random Tests codeforces 1743D

Problem - D - Codeforces

题目大意:有一个长度为n的由0和1组成的字符串,现要求选择两个子串,使得这两个子串的按位或最大,求这个最大值,

5<=n<=1e6

思路:因为要按位或最大,所以我们选择的一个子串一定是原字符串去掉前缀0后的子串,之后要想或运算的结果最大,就要让最靠左的0都优先变成1,所以我们枚举从最靠左的0左边的每个1开头的子串,每个子串的长度为从第一个0到末尾的长度,然后找到所有子串中最大的那个,时间复杂度为O(第一个1到1右边第一个0的长度*这个0到原字符串末尾的长度)因为每个位置上是0或1的概率为1/2,所以1右边的第一个0有很大概率出现前10个位置,时间复杂度近似于O(n)所以按以上方法枚举不会超时,如果数据不是随机生成的,那么时间复杂度肯定是O(n*n)

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e6 + 5;
char s[N];
int pos0;
int main()
{
	int n;
	cin >> n;
	int cnt = 0;
	char c;
	getchar();
	bool flag = 0;//判断有没有1
	int pos1;//记录第一个1的位置
	for (int i = 0; i < n; i++)
	{
		scanf("%c", &s[i]);
		if (!flag && s[i] == '1')
		{
			flag = 1;
			pos1 = i;
		}
		if (!cnt&&flag && s[i] == '0')
		{
			pos0 = i;//记录第一个右边第一个0的位置
			cnt++;//统计0的数量
		}
	}
	if (!flag)
	{//字符串中没有1,直接输出0
		printf("0");
		return 0;
	}
	if (flag&&!cnt)
	{//字符串中没有0//直接输出1
		for (int i = 1; i <= n; i++)
		{
			printf("1");
		}
		return 0;
	}
	string ans;
	for (int i = pos1; i < pos0; i++)
	{//枚举以第一个1到第一个0之间的每个1为子串开头
		string temp = s;
		for (int j = i, k = pos0; k < n; j++, k++)
		{//维护两个指针从第一个1开始遇到一个1,就把第一个0右边对应位置变成1
			if (s[j] == '1')
				temp[k] = '1';
		}
		ans = max(temp, ans);//找出所有子串中的最大值
	}
	for (int i = pos1; i < n; i++)
	{//从第一个1开始到n输出
		printf("%c", ans[i]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timidcatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值