• agc020_d Min Max Repetition


    agc020_d Min Max Reptition

    https://atcoder.jp/contests/agc020/tasks/agc020_d

    定义 (f(A,B)) 为参数为两个正整数 (A,B) ,结果为一个字符串的函数.

    (f(A,B)) 满足以下要求

    1. 长度为 (A+B)
    2. (A) 个'A'和 (B) 个'B'
    3. 在满足1,2的条件下,最小化连续的'A'或'B'的长度
    4. 在满足1,2,3的条件下,最小化字典序

    (Q) 组询问,每组询问给出 (A,B,C,D) ,求 (f(A,B)[C cdots D])

    (1 le Q le 10^3)

    (1 le A_i,B_i le 5 imes 10^8)

    (1 le C_i le D_i le A_i+B_i)

    (D_i-C_i+1 le 100)

    Tutorial

    (K)(f(A,B)) 中最长相同字符连续段的长度.考虑求出 (K)

    不妨设 (A<B) ,根据抽屉原理,将 (B) 个字符放入 (A+1) 个抽屉中.所以得到

    [K=lceil dfrac {B}{A+1} ceil ]

    也就是说,有

    [K = lceil dfrac {max{A_i,B_i}}{min{A_i,B_i}+1} ceil ]

    我们考虑贪心构造,即依次填入每个字符,满足

    1. 当前连续字符长度小于等于 (K)
    2. 存在填补后面的字符串的合法方案

    发现在一段前缀中,第2个条件是没有限制的.所以这段前缀形如"AA...ABA...ABAA..."其中除了最后一段外其他部分的'A'的连续段的长度为 (K) .

    对于剩下的部分,设还有 (A') 个'A'和 (B') 个'B',此时一定有 (B' le K(A'+1)) .

    那么我们可以贪心的先放置一段连续的'B',使得 (B'=KA') ,之后的部分形如"ABB...BABB...B..."其中'B'的连续段长度均为 (K)

    那么我们只需要知道第一部分的长度,就可以很容易得到整个串的形态, (O(1)) 的得知每个位置的字符了.

    考虑二分第一部分的'A'的数量 (Na) ,则 (Nb=lfloor dfrac {Na-1}K floor) ,那么就可以得到 (A',B') 判断.

    时间复杂度 (O(Q(log A+D_i-C_i+1))

    Code

    #include <algorithm>
    #include <cstdio>
    #include <iostream>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    inline char nc()
    {
    //	return getchar();
    	static char buf[100000],*l=buf,*r=buf;
    	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
    }
    template<class T> void read(T &x)
    {
    	x=0; int f=1,ch=nc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
    	x*=f; 
    }
    typedef long long ll;
    int A;
    int B;
    int C;
    int D;
    int K;
    int Q;
    bool check(int Na)
    {
    	int Nb=Na==0?0:(Na-1)/K;
    	return (B-Nb)<=(ll)(A-Na+1)*K;
    }
    int main()
    {
    	read(Q);
    	for(int kase=1;kase<=Q;++kase)
    	{
    		read(A),read(B),read(C),read(D);
    		K=(max(A,B)-1)/(min(A,B)+1)+1;
    		int l=0,r=A,Na=-1;
    		while(l<=r)
    		{
    			int mid=(l+r)>>1;
    			if(check(mid)) Na=mid,l=mid+1;
    			else r=mid-1;
    		}
    		int Nb=Na==0?0:(Na-1)/K;
    		int t=(B-Nb)-(A-Na)*K;
    		for(int i=C;i<=D;++i)
    		{
    			int x=i;
    			if(x<=Na+Nb) putchar(x%(K+1)==0?'B':'A');
    			else
    			{
    				x-=Na+Nb;
    				if(x<=t) putchar('B');
    				else
    				{
    					x-=t;
    					putchar(x%(K+1)==1?'A':'B');
    				}
    			}
    		}
    		putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    [转] 在安卓设备上使用 Chrome 远程调试功能
    如何在移动设备上调试网页
    [转] 函数式编程初探
    如何简单区分Web前后端与MVC
    [转] 钉钉的H5性能优化方案
    js 数组赋值问题 :值传递还是引用?
    (转载)How browsers work--Behind the scenes of modern web browsers (前端必读)
    [转] React 最佳实践——那些 React 没告诉你但很重要的事
    RAII惯用法详解
    [2] 智能指针
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/12991902.html
Copyright © 2020-2023  润新知