「题解」Codeforces 1394C Boboniu and String
orz qyc
两个串相似实际上是两个字符串 'N' 和 'B' 的数量一致。
设 \(s_i\) 有 \(x_i\) 个 'N',\(y_i\) 个 'B',\(t\) 有 \(x\) 个 'N',\(y\) 个 'B'。
分类讨论一下 \(dist(s,t)\) 在 \(x,x_i\) 以及 \(y,y_i\) 大小关系不同的四种情况下的取值。
发现四种情况分别为:
\(x-y-x_i+y_i,-(x-y)+x_i-y_i,\max(x_i-x,y_i-y),\max(x-x_i,y-y_i)\)
对出现的六个式子求 \(\max\) 恰好为答案,具体为何同样可以分类讨论四种情况。
二分答案转判定,就变成要求 \(\max\) 里面六个值都 \(\geq mid\)。
发现实际上是对 \(x,y,x-y\) 的取值范围作出限制。
后面就很简单了,算出各自的取值范围,然后看前两项不等式的差出来的范围是否和后一项的范围有交即可,构造方案枚举个 \(x\) 随便怎么构造都可。
其实分类讨论有很多细节,但是这里仅给出主要思路不商讨细节部分。
//Code by do_while_true
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
typedef long long ll;
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T> T Abs(T x) { return x < 0 ? -x : x; }
template <typename T> T chkmax(T &x, T y) { return x = x > y ? x : y; }
template <typename T>
T &read(T &r) {
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = (r << 3) + (r <<1) + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
const int N = 300010;
const int INF = 100000000;
int n, a[N], b[N];
//a:N b:B
char ch[N];
bool check(int x) {
int l1, r1, l2, r2, l3, r3;
l1 = -INF, r1 = INF; l2 = 0, r2 = INF; l3 = 0; r3 = INF;
for(int i = 1; i <= n; ++i) {
l1 = Max(l1, a[i]-b[i]-x);
r1 = Min(r1, a[i]-b[i]+x);
l2 = Max(l2, a[i]-x);
r2 = Min(r2, a[i]+x);
l3 = Max(l3, b[i]-x);
r3 = Min(r3, b[i]+x);
}
if(l2 < 0 || l3 < 0) return 0;
if(l1 > r1 || l2 > r2 || l3 > r3) return 0;
int l4 = l2 - r3, r4 = r2 - l3;
return r1 >= l4 && l1 <= r4;
}
signed main() { //freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
read(n);
if(n == 1) {
scanf("%s", ch+1);
puts("0");
printf("%s\n", ch+1);
return 0;
}
for(int i = 1; i <= n; ++i) {
scanf("%s", ch+1);
int len = std::strlen(ch+1);
for(int j = 1; j <= len; ++j)
if(ch[j] == 'N') ++a[i];
else ++b[i];
}
int l = 0, r = INF, mid, ans = 0;
while(l <= r) {
mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid-1;
else l = mid+1;
}
printf("%d\n", ans);
int l1, r1, l2, r2, l3, r3;
l1 = -INF, r1 = INF; l2 = 0, r2 = INF; l3 = 0; r3 = INF;
for(int i = 1; i <= n; ++i) {
l1 = Max(l1, a[i]-b[i]-ans);
r1 = Min(r1, a[i]-b[i]+ans);
l2 = Max(l2, a[i]-ans);
r2 = Min(r2, a[i]+ans);
l3 = Max(l3, b[i]-ans);
r3 = Min(r3, b[i]+ans);
}
int l4 = l2 - r3, r4 = r2 - l3;
l = Max(l1, l4); r = Min(r1, r4);
for(int i = l2; i <= r2; ++i) {
int _l = i - r3, _r = i - l3;
if(Max(_l, l) <= Min(r, _r)) {
int p = Max(_l, l);
if(i || (i-p)) {
for(int j = 1; j <= i-p; ++j) printf("B");
for(int j = 1; j <= i; ++j) printf("N");
return 0;
}
else {
p = Min(r, _r);
if(i || (i-p)) {
for(int j = 1; j <= i-p; ++j) printf("B");
for(int j = 1; j <= i; ++j) printf("N");
return 0;
}
}
}
}
return 0;
}