【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
View Code

 

posted @ 2018-01-15 10:40  ONION_CYC  阅读(798)  评论(0编辑  收藏  举报