CF1394C Boboniu and String
阿新 • • 發佈:2021-10-27
題解
好妙的一道題。
將每個串都抽象成二維平面上的一個點 \((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; }