首页 > 其他分享 >[ARC169E] Avoid Boring Matches 题解

[ARC169E] Avoid Boring Matches 题解

时间:2024-01-17 19:12:16浏览次数:19  
标签:ch 匹配 前缀 题解 ll ARC169E 判定 Boring 我们

题目链接

首先考虑无解的情况,一个显然的观察是如果 R 的个数大于一半,那么无论如何都会出现两个 R 比赛的情况,小于一半时我们可以调整使得 B 全都在前面,显然有解。

接下来问题变为找到最优可行解,但是状态的合法性不是显然的,我们先尝试判定这个问题。

先考虑第一轮比赛,显然我们想让 B 获胜的尽可能多且编号尽可能靠前,因此,我们从左往右扫描序列,如果一个 B 还没有对手,那么从后面找到一个最接近的 R 当它的对手肯定最优,因为这样既能保证保留较小的 B 又能尽量把 较大的 R 留到后面,而最后没匹配到的无论怎么匹配结果肯定都一样。

这样对每一轮进行这个操作,如果过程中出现了不合法的情况即为无解,但是这样暴力进行判定并转移还是太慢了,现在要么优化转移要么优化判定,但这个题目在转移上没有什么特别好的性质,我们先尝试在判定方面进行优化

考虑每一轮匹配的时候能不能不进行实际操作,只靠某些关键信息就能判定无解,由于上文我们提到在匹配完后没匹配到的无论怎么匹配结果都是一样,因此我们可以将某些 BB 匹配的对子中最后一个 B 换成 R,这样可以少考虑一个个数的因素。

剩下的就是位置的信息了,你发现第一个 B 靠前会优,而靠后到某一位置后可能就无解,其他的也一样,这个位置比较的过程其实有点像比较字典序,那存不存在一个最劣字符串使得比这个字符串大的字符串都可行呢?

实际上是存在的,但是由于这个消除的过程类似二分图匹配,这个大小关系的比较不是简单地比较字典序,而是考虑将 R 设为 -1,B 设为 1 并计算前缀和,我们要求前缀和每一位都大于等于最劣串的前缀和。

这个结论的充分性可以用归纳法证明,或者你可以感性地想象一下相消的过程,总之,这个字符串不仅存在,并且是易于通过递归求出的,当我们得到前一轮的最劣串时,由于每个 B 此时又可以解决一个 R,因此我们在每个 B 后面紧跟一个 R 表示字典序最小,然后在最后补齐 B 就可以了。

答案的计算则是简单的,由于我们要前缀和全部大于等于,且一次交换能将前缀差值增加 2,因此只要计算不够的部分的和然后除以 2 即可。

#include<bits/stdc++.h>
#define ll long long
#define N 2000005
using namespace std;
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9')f=(ch=='-'?-1:1),ch=getchar();
	while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x*f;
}
void write(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
ll a[N];
int main(){
	ll n=read(),cnt=0;
	string s="RB";
	for(ll i=2;i<=n;i++){
		string t="";
		for(ll i=0;i<s.length();i++){
			t+=s[i];if(s[i]=='B')t+='R';
		}
		while(t.length()<(1<<i))t+='B';
		s=t;
	}	
	string t;cin>>t;ll S=0;
	for(ll i=0;i<(1<<n);i++)cnt+=(t[i]=='R');
	if(cnt>(1<<(n-1))){cout<<-1;return 0;}
	for(ll i=0;i<(1<<n);i++)a[i]+=(s[i]=='R'?-1:1),a[i]-=(t[i]=='R'?-1:1);
	for(ll i=0;i<(1<<n);i++){
		if(i!=0)a[i]+=a[i-1];
		S+=(a[i]>0?a[i]:0);
	}
	cout<<S/2;
	return 0;
}

标签:ch,匹配,前缀,题解,ll,ARC169E,判定,Boring,我们
From: https://www.cnblogs.com/eastcloud/p/17970806

相关文章

  • SP839Optimal Marks 题解
    part1:建图二进制异或,每一位互不干扰。所以对每一位分开来考虑。然后变成了一个经典的模型。当前每一个未确定点有两个选择:变成\(1\),变成\(0\);已经确定的点只能选它本身的值。于是构造思路非常套路了:构造虚点\(S\)、\(T\)。对于一个点\(u\),从\(S\)连向\(u\)一条边,值为......
  • ABC311_g One More Grid Task 题解
    题目链接:Atcoder或者洛谷对于解决二维区间内的最值类型问题,我们常常有一类特别好用的方法,就是悬线法,它可以看做是单调栈的子集,但更加好理解和书写。对于悬线法,我们有一个常见的模型,找出面积最大的符合题意的最大的矩形:例题P4147玉蟾宫。对于悬线法而言,我们需要理解什么是悬......
  • P2216 [HAOI2007] 理想的正方形 题解
    题目链接:理想的正方形比较明显的,我们可以用二维ST表解决,具体的二维ST表的实现,只需要知道一点:对于\(st[i][j][t]=max(i\simi+2^t,j\simj+2^t)\),表示的是如图所示的大正方形范围内的最值,它可以拆成从四个小正方形的左端点走\(2^{t-1}\)长的小正方形组成,预处理完直接查......
  • 【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(上)
    知识盲点概念介绍HashMap是基于Map接口构建的数据结构,它以键值对的形式存储元素,允许键和值都为null。由于键的唯一性,HashMap中只能有一个键为null。HashMap的特点是元素的无序性和不重复性。注意,HashMap并不是线程安全的。在多线程环境下,如果不进行适当的同步处理,可能会导致数据不......
  • P9018 [USACO23JAN] Moo Route G 题解
    首先有一些性质。因为保证有解,所以\(a_i\)一定都是\(2\)的倍数(必须一来一回)。并且总的步数应该为\(\suma_i\)。先考虑\(n\le2\)的情况,这时我们可以分情况讨论。因为每一条线段都会被来回走两次,所以我们可以先把每一个数都除以\(2\)。若\(a=b\),则最优情况一定是形......
  • P9017 [USACO23JAN] Lights Off G 题解
    一次操作相当于把\(a\)异或上\(b\),修改开关的一位相当于将这一位异或上\(1\)。会发现一个很神奇的性质:初始开关对灯的影响和改变开关状态对灯的影响是独立的。而前者的影响是固定的,所以我们可以只考虑改变开关状态对灯的影响。假设一共需要\(k\)次操作能使所有灯关闭,如果我......
  • CF1876D Lexichromatography 题解
    Problem-D-CodeforcesLexichromatography-洛谷先注意读题:对于所有的值\(k\),在这个序列的任意子区间\([l,r]\)中,值为\(k\)且为红色的位置数减去值为\(k\)且为蓝色的位置数的绝对值不超过\(1\)注意是任意子区间这说明什么?说明如果只有第二个条件,我......
  • P2572 [SCOI2010] 序列操作 题解
    题解:序列操作比较综合的ds题,综合了线段树常见的几种操作:维护最大子段和、区间翻转、区间求和、区间覆盖。维护子段和常见的我们维护三类东西:前缀最长连续段、后缀最长连续段、当前区间上的最大子段和。在pushUp时,对于一个区间的前后缀最值首先等于左右子树的最长前后缀,......
  • P6054 题解
    blog。网络流——最小割。每个选手做某一套题的期望奖励固定,计算方式参考样例解释。这个假期望被去掉了。发现是典型的「\(m\)种强制选一」问题。考虑每个人都建一条链,跑最小割,每条链必定割\(\ge1\)条边,割哪条边就表示选哪套题。code,时间复杂度\(O(\text{能过})\)。......
  • 洛谷P10058 题解
    这种翻转的题明显已经做烂了好吧……首先显而易见,翻转偶数次对结果没有影响,只需要考虑奇数次翻转的情况。由于是整体移动的操作,可以抓住一个点来移动,然后还原出原来的序列。需要注意的是字符串是环形移动,因此如果当前点的位置大于字符串长度,要对字符串的长度进行取余操作。写......