CodeForces #664F - Boboniu and String

传送门

题意

给定n个由B和N组成的字符串s1,s2……sn,一个字符串每次可以做以下操作中的一个
1.删除或增加一个B
2.删除或增加一个N
3.删除或增加一个BN
4.删除或增加一个NB
求一个由N,B组成的字符串t,要求t转换到所有字符串s的操作次数的最大值最小,使得t与s的B,N字符数量相等。

思路

首先一个字符串与其 N、B 的顺序无关,只与 N、B 的数量有关,所以可以表示为平面上一个点 (xi,yi)
求最大值最小考虑二分,这个也很平凡。然后两个点的距离的定义也很显然:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define maxn 500005
#define mod 998244353
ll maxa=0,mina=inf,maxb=0,minb=inf,mxd=-inf,mnd=inf;
ll ansb=0,ansn=0;
char s[maxn];

bool check(ll mid){
    ll minx=max(0ll,maxa-mid),maxx=mina+mid,miny=max(0ll,maxb-mid),maxy=minb+mid,maxd=mnd+mid,mind=mxd-mid;
    if(minx>maxx||miny>maxy||mind>maxd) return false;
    if(miny-maxx>maxd||maxy-minx<mind) return false;
    if((maxd>=maxy-maxx)&&(mind<=maxy-maxx)) ansn=maxx,ansb=maxy;
    else if(mind>=maxy-maxx) ansb=maxy,ansn=maxy-mind;
    else{
        ansn=maxx,ansb=maxx+maxd;
    }
    /*if (maxd >= maxy - minx && mind <= miny - maxx) ansn=maxx, ansb=maxy;
    else if (maxd <= maxy - maxx) ansn=maxx, ansb=maxx + maxd;
    else if (maxd <= maxy - minx) ansn=maxy - maxd, ansb=maxy;
    else if (mind >= maxy - maxx) ansn=maxy - mind, ansb=maxy;
    else if (mind >= miny - maxx) ansn=maxx, ansb=maxx + mind;*/
    return true;
}

int main(){
    ll i, n, j, k, t;
    scanf("%lld",&n);
    for(i=1;i<=n;i++){
        scanf("%s",s);
        k=strlen(s);
        ll a=0,b=0;
        for(j=0;j<k;j++){
            if(s[j]=='N') a++;
            else b++;
        }
        mina=min(mina,a),maxa=max(a,maxa);
        minb=min(minb,b),maxb=max(b,maxb);
        mxd=max(mxd,b-a),mnd=min(mnd,b-a);
    }
    ll l=0,r=500005;
    while(l<r){
        ll mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    check(l);
    printf("%lld\n",l);
    for(i=1;i<=ansb;i++) printf("B");
    for(i=1;i<=ansn;i++) printf("N");
    printf("\n");
}