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;
}
原文地址:https://www.cnblogs.com/ljzalc1022/p/12991902.html