【Atcoder】AGC 020 D - Min Max Repetition 二分+构造
【题意】定义f(A,B)为一个字符串,满足:
1.长度为A+B,含有A个‘A',B个'B'。
2.最长的相同字符子串最短。
3.在满足以上2条的情况下,字典序最小。
例如, f(2,3) = BABAB
, and f(6,4) = AABAABAABB
.
Q次询问f(Ai,Bi)的子串[Ci,Di]。
Q<=10^3,A,B<=5*10^8,D-C+1<=100,time=2s。
【算法】二分+构造
【题解】参考:Editorial
令k为最短的最长相同字符子串,显然k=max(A,B)/(min(A,B)+1)(上取整)。
考虑某个位置填入’A‘后合法,应满足:
1.当前连续A不超过k。
2.剩余的A’和B'构成的k(A',B')<=k(A,B)。
顺序扫描即可得到全串——部分分。
分析答案串的构造,前面应为A...ABA...ABA...A,直到某个位置p不满足B<=A*k为止。
此时位置p一定是‘A',且B-A*k<=k,后面就不得不排列成B...BAB...BAB...B。
二分位置p,输出c~d即可。
#include<cstdio> #include<algorithm> using namespace std; int T,k,n,a,b,c,d; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d%d",&a,&b,&c,&d);n=a+b; int l=0,r=n+1,mid,A,B;k=(max(a,b)-1)/(min(a,b)+1)+1;; while(l<r){ mid=(l+r)>>1; A=a-mid/(k+1)*k-mid%(k+1);B=b-mid/(k+1); if(B<=1ll*A*k)l=mid+1;else r=mid; } A=a-l/(k+1)*k-l%(k+1);B=b-l/(k+1);r=l+B-A*k+1; for(int i=c;i<=min(d,l);i++)putchar(i%(k+1)?'A':'B'); for(int i=max(c,l+1);i<=d;i++)putchar((i-r)%(k+1)?'B':'A'); puts(""); } return 0; }//ONION_CYC QwQ