Loading

题解「Japan Alumni Group Summer Camp 2018 Day 2J AB Sort」

GMOJ100137 胖头鱼的排序

题意

对字符串 \(s\) 进行一次操作,使得 \(s\) 中所有为 \(\text{BA}\) 的子串同时变为 \(\text{AB}\) 。定义 \(\mathrm{f}(s)\) 表示不断对 \(s\) 进行上述操作,直到无法再操作为止,最多能对 \(s\) 进行的操作次数。

给定字符串 \(s\) ,要求支持区间 \(\text{AB}\) 翻转,查询 \(\mathrm{f}('\mathrm{B}'+s+'\mathrm{A}')\)

题解

发现进行这样的操作的本质是对 \(s\) 排序,最后所有的 \(\text{A}\) 都在 \(\text{B}\) 的前面。也就是说,只要存在一个 \(\text{B}\)\(\text{A}\) 前面,那么这个字符串就还能被操作。发现所有 \(\text{B}\) 的相对位置是不变的,所以只需要考虑最左边的那个 \(\text{B}\) 被移动到正确的位置上的操作次数。

显然,如果每次操作都让最左边的 \(\text{B}\) 移动了一位,那么总操作次数即为 \(\mathrm{cnt}(\text{A})+1\) (这里 \(\mathrm{cnt}\) 计算的是 \(s\) 中字母的个数,不包括两段加入的字符),但是并不是每次操作都会移动最左边的 \(\text{B}\) 。不难发现,本次操作不会移动某个位置的 \(\text{B}\) ,当且仅当它后面紧跟着一个 \(\text{B}\) ,而不是 \(\text{A}\)(后面没有字符除外),我们将这种情况称作这个 \(\text{B}\) 被后面的 \(\text{B}\) 阻挡。

考虑下面这种情况(假设最后一段 \(\text{A}\) 足够长):

\[\text{B}~\overbrace{\text{AA}\ldots\text{AA}}^{c_1}~\overbrace{\text{BB}\ldots\text{BB}}^{c_2}~\text{AA}\ldots \]

\(c_1\geq c_2\) ,那么当最左边的 \(\text{B}\) 移动到第一段 \(\text{A}\) 之后时,长度为 \(c_2\) 的那段 \(\text{B}\) 已经全部移动,即此时最左边的 \(\text{B}\) 后面紧接着的是一个 \(\text{A}\) ,那么它就可以继续向后移动,换而言之,这段长度为 \(c_2\)\(\text{B}\) 对最左边的 \(\text{B}\) 的移动无影响。

否则 \(c_1<c_2\) ,最左边的 \(B\) 移动到 \(\text{A}\) 之后时,后面那段 \(\text{B}\) 还有 \(c_2-c_1\) 个没有移动,即它后面紧接着有 \(c_2-c_1\)\(\text{B}\) ,再进行操作时这个 \(\text{B}\) 就无法移动了,它再次移动还需要 \(c_2-c_1\) 次操作。

如果最后一段 \(\text{A}\) 不够长,即下面一种情况:

\[\text{B}~\overbrace{\text{AA}\ldots\text{AA}}^{c_1}~\overbrace{\text{BB}\ldots\text{BB}}^{c_2}~\overbrace{\text{AA}\ldots\text{AA}}^{c_3}~\overbrace{\text{BB}\ldots\text{BB}}^{c_4}~\text{AA}\ldots \]

其中 \(c_3<c_4\) ,那么 \(c_2\) 这一段就不能顺利地走过 \(c_3\) 这一段了,它会被后面 \(c_4\) 这一段阻挡 \(c_4-c_3\) 次操作,那么最左边的 \(\text{B}\) 就会被阻挡 \(c_4+c_2-c_1-c_3\) 次操作。

到这里就能大概看出结论了:若将 \(\text{A}\) 看成 \(-1\)\(\text{B}\) 看成 \(1\) ,序列的最大前缀和为 \(\mathrm{lmax}(s)\) ,答案即为 \(\mathrm{cnt}(\text{A})+1+\mathrm{lmax}(s)\)

用线段树维护即可。

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <climits>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=2e5+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,q;
char s[maxn];

namespace Segment_Tree
{
	struct node
	{
		int l,r,cntA,cntB;
		int sum,lmin,lmax;
		bool tag;
		node(int l,int r,int cntA,int cntB,int sum,int lmin=0,int lmax=0,bool tag=false)
			:l(l),r(r),cntA(cntA),cntB(cntB),sum(sum),lmin(lmin),lmax(lmax),tag(tag){}
		node(){}
		inline node operator + (const node &T)const
		{
			node res(l,T.r,cntA+T.cntA,cntB+T.cntB,sum+T.sum);
			res.lmin=min(lmin,sum+T.lmin);
			res.lmax=max(lmax,sum+T.lmax);
			return res;
		}
	}tree[maxn<<2];
	#define ls (p<<1)
	#define rs (p<<1|1)
	inline void reverse(int p)
	{
		if(!p) return;
		swap(tree[p].cntA,tree[p].cntB);
		swap(tree[p].lmin,tree[p].lmax);
		tree[p].lmin=-tree[p].lmin;
		tree[p].lmax=-tree[p].lmax;
		tree[p].sum=-tree[p].sum;
		tree[p].tag^=1;
	}
	inline void push_down(int p)
	{
		if(!tree[p].tag) return;
		reverse(ls);
		reverse(rs);
		tree[p].tag=0;
	}
	inline void set(int p,char c)
	{
		tree[p].sum=c=='A'?-1:1;
		c=='A'?(tree[p].cntA=1):(tree[p].cntB=1);
		tree[p].lmin=min(0,tree[p].sum);
		tree[p].lmax=max(0,tree[p].sum);
	}
	void build(int p,int l,int r)
	{
		tree[p]=node(l,r,0,0,0);
		if(l==r) return set(p,s[l]),void();
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		tree[p]=tree[ls]+tree[rs];
	}
	void modify(int p,int L,int R)
	{
		int l=tree[p].l,r=tree[p].r;
		if(L<=l&&r<=R) return reverse(p),void();
		push_down(p);
		int mid=(l+r)>>1;
		if(L<=mid) modify(ls,L,R);
		if(R>mid) modify(rs,L,R);
		tree[p]=tree[ls]+tree[rs];
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("P100137.in","r",stdin);
#endif
	read(n);
	scanf(" %s\n",s+1);
	Segment_Tree::build(1,1,n);
	read(q);
	int l,r;
	while(q--)
	{
		read(l),read(r);++l,++r;
		Segment_Tree::modify(1,l,r);
		printf("%d\n",Segment_Tree::tree[1].cntA+Segment_Tree::tree[1].lmax+1);
	}
	return 0;
}

posted @ 2020-11-14 14:41  GoPoux  阅读(190)  评论(0编辑  收藏  举报