Logo Iceturky 的博客

博客

QOJ504#1289 A + B Problem题解

...
Iceturky
2025-12-01 12:54:31
星屑落ちて 華は散っても キラめく舞台に 生まれて変わる

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-06-25 20:42:54

题意:

给出一个长度为 $n+m$ 的 01串,要求将其划分为两个子序列 $a$ 和 $b$ ,长度分别为 $n$ 和 $m$ ,使每一个元素都恰好在一个子序列内,使这两个子序列视为二进制数后加和最大,求出二进制下最大加和。

scallion 赛时的做法是:使 $n>m$ ,将前 $m$ 个位分给 $b$ ,后 $n$ 个位给 $a$ ,然后两个指针从分界处开始分别往左和右扫,对于左边扫到的 $1$ ,若右边扫到的 $0$ 位权比自己大则交换。

感觉有点对,但不知道为啥能取到上界。

code

const int N=1e6+5;

char s[N];

int ans[N];

signed main(){
	signed _T=read();
	while(_T--){
		int n=read(),m=read();
		scanf("%s",s+1);
		if(n>m)swap(n,m);
		int l=n,r=n+1;
		while(1){
			while(l>0&&s[l]=='0')
				l--;
			while(r<=n+m&&s[r]=='1')
				r++;
			if(l>0&&r<=n+m&&n+m-r>n-l)
				swap(s[l],s[r]);
			else
				break;
		}
		for(int i=1;i<=m;i++)
			ans[i]=s[n+m-i+1]-'0';
		for(int i=1;i<=n;i++)
			ans[i]+=s[n-i+1]-'0';
		for(int i=1;i<=n+m;i++)
			ans[i]+=ans[i-1]>>1,ans[i-1]&=1;
		int len=n+m;
		while(len>1&&ans[len]==0)len--;
		for(int i=len;i>=1;i--)
			pc(ans[i]+'0'),ans[i]=0;
		pc('\n');
	}
	return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。