OnlyPersistVictory DayTen

题意:
给定 a , b a,b a,b和串 s s s s s s只包含三种字符1 0 ?。问是否可以将 s s s中的?转换成01,使得 s s s被构造成恰好有 a a a0 b b b1的回文串。可以则输出构造的任意一种合法回文串,否则输出-1
数据范围: 0 ≤ a , b ≤ 2 × 1 0 5 , a + b ≥ 1 0\leq a,b\leq 2\times 10^5,a+b\geq 1 0a,b2×105,a+b1

题解:
先考虑所有已经可以确定的位置,即其位置或其回文位置已经有数字了,则可以直接放相应数字,否则根据 a , b a,b a,b的大小看可以放的字符。记得特判串为奇数的中间位置的情况。

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 2e5 + 10;
char s[N];
int a, b;

void solve() {
    
    
	scanf("%d%d", &a, &b);
	scanf("%s", s);
	int n = strlen(s);
	int f = 1, c = 0;
	for(int i = 0; i < n >> 1; ++i) {
    
     
		if(n % 2 && i == n - 1 - i) continue;
 		if(s[i] == '?' && s[n - 1 - i] == '?') continue;
		if(s[i] == '?') {
    
    
			int v = s[n - i - 1] - '0';
			if(v == 0) a -= 2;
			else b -= 2;
			s[i] = v + '0';
		}
		else if(s[n - i - 1] == '?') {
    
    
			int v = s[i] - '0';
			if(v == 0) a -= 2;
			else b -= 2;
			s[n - i - 1] = v + '0';
		}
		else if(s[i] != s[n - i - 1]) f = 0;
		else if(s[i] == '1') b -= 2;
		else a -= 2;
	}
	
	for(int i = 0; i < n >> 1; ++i) {
    
     
		if(n % 2 && i == n - 1 - i) continue;
		if(s[i] == '?') {
    
    
			if(a > 1) a -= 2, s[i] = s[n - i - 1] = '0';
			else if(b > 1) b -= 2, s[i] = s[n - i - 1] = '1';
			else f = 0;
		}
	}
	
	if(n % 2) {
    
    
		if(s[n >> 1] == '0') --a;
		else if(s[n >> 1] == '1') --b;
		else {
    
     
			if(a >= 1) s[n >> 1] = '0', --a;
			else if(b >= 1) s[n >> 1] = '1', --b;
			else f = 0;
		} 
	}
	if(a != 0 || b != 0) f = 0;
	if(f) puts(s);
	else puts("-1");
}

int main()
{
    
    
	int T = 1;
	scanf("%d", &T);
	for(int i = 1; i <= T; ++i) solve();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43900869/article/details/115607616