GYM103371B Cilantro 做题记录

给定 nn 和两个长 nn0101SSTT

设入栈序列为 SS,出栈序列为 TT 的所有栈操作序列中,T1T_1 可能对应的 SS 中的下标集合为 AA

xAx\sum\limits_{x\in A}x

例如 S=100S=100T=001T=001 时答案为 55,因为共有 22 种栈操作序列满足入栈序列为 SS,出栈序列为 TT

  • 进,进,进,出,出,出,此时 T1T_1 来自 S3S_3
  • 进,进,出,进,出,出,此时 T1T_1 来自 S2S_2

所以答案为 3+2=53+2=5

1n5×1061\le n\le 5\times 10^6

首先有个结论,对于任意两个 00 的个数相等且 11 的个数相等的 0101 序列 AABB,总有合法的栈操作序列满足入栈序列为 AA 且出栈序列为 BB

证明十分简单,考虑贪心,从左往右逐位考虑 AA,设当前出栈序列已经匹配 jj 个,则若栈顶元素 x=Bj+1x\not=B_{j+1}Ai=Bj+1A_i\not=B_{j+1}AiA_i 入栈, 否则 jj+1j\to j+1。这样栈中不会同时出现两种不同元素,一定可以构造出来。

考虑从 11 开始,逐个确定 SiS_i 是否有可能去到 T1T_1。先不考虑 Si=T1S_i\not= T_1 的情况,那么若 SiS_i 去了 T1T_1,则 SiS_i 出栈时 S[1,i1]S_{[1,i-1]} 一定都在栈中。

所以可以找到 ijposi1i\le j\le pos_{i-1}S[i,j]S_{[i,j]}00 的个数等于 T[1,ji+1]T_{[1,j-i+1]}00 的个数的最大的 jj,令 posi=jpos_i=j;找不到则 posi=1pos_i=-1,求出 posipos_i 后可以这样构造:

那么显然答案即为 posi=1i\sum\limits_{pos_i\not=-1}i,问题变成求解 posipos_i,双指针即可,时间复杂度 O(n)O(n)

代码如下:

// Problem: B. Cilantro
// Contest: XXII Open Cup, Grand Prix of Korea
// URL: https://codeforces.com/gym/103371/problem/B
// Memory Limit: 1024 MB
// Time Limit: 500 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <iostream>
#include <cstdio>

using namespace std;

const int S=5000005;

int n;
char a[S],b[S];
int sa[S],sb[S];
int pos[S];

int main()
{
	scanf("%d",&n);
	scanf("%s%s",a+1,b+1);
	for(int i=1;i<=n;i++) sa[i]=sa[i-1]+(a[i]=='Y'),sb[i]=sb[i-1]+(b[i]=='Y');
	for(int i=1,r=n;i<=n;i++)
	{
		while(r>=i&&sa[r]-sa[i-1]!=sb[r-i+1]) r--;
		pos[i]=r;
	}
	long long ans=0;
	for(int i=1;i<=n;i++) if(pos[i]>=i&&a[i]==b[1]) ans+=i;
	printf("%lld\n",ans);
	return 0;
}