USACO22OPEN-Silver C


USACO22OPEN-Silver C

前言(Front talk)

$\qquad$比较简单。(甚至想把这个题的前言删掉)

网址(Website)

$\qquad$洛谷: USACO22OPEN COW Operations S

$\qquad$SPOJ: 题目详情 - COW Operations - Super

$\qquad$SPOJ: 题解 - COW Operations - Super

题目(Problem)

$Bessie$ 找到了一个长度不超过 $2 \cdot 10^5$ 且仅包含字符 ‘C’,’O’ 和 ‘W’ 的字符串 $s$。她想知道是否可以使用以下操作将该字符串变为单个字母 ‘C’(她最喜欢的字母):

  1. 选择两个相邻相等的字母并将其删除。

  2. 选择一个字母,将其替换为另外两个字母的任一排列。

求出这个字符串本身的答案对 $Bessie$ 而言并不足够,所以她想要知道 $s$ 的 $Q$($1\le Q\le 2\cdot 10^5$)个子串的答案。

输入格式(Input)

输入的第一行包含 $s$。

第二行包含 $Q$。

以下 $Q$ 行每行包含两个整数 $l$ 和 $r$($1\le l\le r\le |s|$,其中 $|s|$ 表示 $s$ 的长度)。

输出格式(Output)

输出一个长为 $Q$ 的字符串,如果第 $i$ 个子串可以被转变则第 $i$ 个字符为 ‘Y’,否则为 ‘N’。

样例(Example)

样例输入

COW
6
1 1
1 2
1 3
2 2
2 3
3 3

样例输出

YNNNYN

提示(Notice)

【样例解释】

第一个询问的答案是「是」,因为 s 的第一个字符已经等于 ‘C’。

第五个询问的答案是「是」,因为 s 的第二到第三个字符组成的子串 OW 可以通过两步操作变为 ‘C’:

   OW
-> CWW
-> C

这个样例字符串 COW 的其他子串均不能被转变为 ‘C’。

【测试点性质】

  • 测试点 $2-4$ 满足 $|s|\le 5000$ 以及 $Q\le 5000$。
  • 测试点 $5-11$ 没有额外限制。

题解(Solution)

容易得到几个性质:

  • 任两个字母可以交换
  • 任两个不同字母可以合成一个字母
  • 任两个相等字母可以抵消

然后直接记录三个字母的前缀数量,到时候直接差分求字母数,$mod\ 2$ 后判断剩下的能不能组成字母 $C$ 即可。

代码(Code)

#include<bits/stdc++.h>
#define For(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
inline int input(){int x;return cin>>x,x;}
const int N = 201234;
char a[N];
int n,q;

int c[N],o[N],w[N];

inline bool check(int l,int r){
	int C=(c[r]-c[l-1])%2;
	int O=(o[r]-o[l-1])%2;
	int W=(w[r]-w[l-1])%2;
	if(C==1 && O==0 && W==0) return true;
	if(C==0 && O==1 && W==1) return true;
	return false;
}

signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	string str("cowoper");
	freopen((str+".in").c_str(),"r",stdin);
	freopen((str+".out").c_str(),"w",stdout);
	cin>>(a+1)>>q;
	n=strlen(a+1);
	For(i,1,n){
		c[i]=c[i-1],o[i]=o[i-1],w[i]=w[i-1];
		if(a[i]=='C') c[i]++;
		if(a[i]=='O') o[i]++;
		if(a[i]=='W') w[i]++;
	}
	while(q--){
		int l=input(),r=input();
		cout<<(check(l,r)?'Y':'N');
	}return 0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录