CF1394C Boboniu and String
题解
好妙的一道题。
将每个串都抽象成二维平面上的一个点 \((x_i,y_i)\),\(x_i\) 为其中 N
的个数,\(y_i\) 为 B
的个数。
二分答案 \(mid\),那么对于一个点 \((x_i,y_i)\),能通过不超过 \(mid\) 次操作到达它的点的范围是一个凸六边形,所以可以用不等式描述这个范围:
\[\begin{aligned}
&x_i-mid\le x\le x_i+mid\\
&y_i-mid\le x\le y_i+mid\\
&x_i-y_i-mid\le x-y\le x_i-y_i+mid\\
\end{aligned}
\]
对所有的 \(i\),将以上范围求交即可。
有些细节。
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <utility>
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
template<typename T>
void Read(T &_x){
_x=0;int _f=1;
char _ch=getchar();
while(!isdigit(_ch)) _f=(_ch=='-'?-1:_f),_ch=getchar();
while(isdigit(_ch)) _x=_x*10+(_ch^48),_ch=getchar();
_x*=_f;
}
template<typename T,typename... Args>
void Read(T &_x,Args& ...others){
Read(_x);Read(others...);
}
typedef long long ll;
typedef pair<int,int> Point;
const int N=3e5+5,Len=5e5+5;
int n;
Point poi[N];
pair<bool,Point> Check(int mid){
int xmin=-Len,xmax=Len,ymin=-Len,ymax=Len,xymin=-Len,xymax=Len;
For(i,1,n){
xmin=max(xmin,poi[i].first-mid);
xmax=min(xmax,poi[i].first+mid);
ymin=max(ymin,poi[i].second-mid);
ymax=min(ymax,poi[i].second+mid);
xymin=max(xymin,poi[i].first-poi[i].second-mid);
xymax=min(xymax,poi[i].first-poi[i].second+mid);
}
xmin=max(0,xmin),ymin=max(0,ymin);
if(xmin>xmax||ymin>ymax||xymin>xymax) return {0,{0,0}};
int xymn=xmin-ymax,xymx=xmax-ymin;
if(xymn>xymax||xymx<xymin) return {0,{0,0}};
xymax=min(xymax,xymx);
xymin=max(xymin,xymn);
int pxmax=min(ymax+xymax,xmax),pymax=min(pxmax-xymin,ymax);
return {1,{pxmax,pymax}};
}
int main(){
Read(n);
char temp[Len];
For(i,1,n){
scanf("%s",temp+1);
int len=strlen(temp+1),cnt=0;
For(j,1,len){
cnt+=temp[j]=='N';
}
poi[i]={cnt,len-cnt};
}
int l=0,r=1e6;
Point ans;
while(l<r){
int mid=(l+r)>>1;
if(Check(mid).first) r=mid,ans=Check(mid).second;
else l=mid+1;
}
printf("%d\n",l);
For(i,1,ans.first) putchar('N');
For(i,1,ans.second) putchar('B');
return 0;
}
Written by Alan_Zhao