可以考虑把字符串 \(s\),\(t\) 按 \(s_1 t_1 s_2 t_2 \dots s_n t_n\) 拼接,记为 \(a\)。为了方便表述,这里分别把 PVW
表示为 012
。
Subtask 0
我会暴力!可以直接在 \(a\) 上进行 dfs,复杂度为 \(O(3^{2n})\)。
Subtask 1
我会找性质!注意到答案只有可能是 \(0,1,2\),因为在最坏情况下,只要 \(2\) 次操作把 \(a_1,a_2,a_3\) 改成互不相同的数就行了。
首先我们可以 \(O(n)\) 判断答案是否为 \(0\)。接下来判断答案是否为 \(1\),我们可以枚举修改哪个位置,再扫一遍 \(a\) 就可以了。剩下的情况的答案必然为 \(2\)。总复杂度为 \(O(n^2)\)。
Subtask 4
考虑在判断答案是否为 \(1\) 的过程上优化,可以发现答案为 \(1\) 时,设获胜的位置为 \(i\),\(s_{0/1/2}\) 表示 \(a_1 \sim a_i\) 中 \(0,1,2\) 出现的个数,则 \(3 \mid i\) 且 \(\{s0,s1,s2\}=\{\frac{i}{3}-1,\frac{i}{3},\frac{i}{3}+1\}\)。于是我们就记录每个 \(a_i\) 最后出现的位置。
但是,如果把某个位置修改后,自己比对手先赢,就会出现问题。于是,我们设 \(lst_{i,j}\) 表示最前的把 \(i\) 改为 \(j\) 且不会出现这种情况的位置。每次出现 \(3 \mid i\) 且 \(\{s0,s1,s2\}=\{\frac{i}{3}-1,\frac{i}{3},\frac{i}{3}+1\}\) 时,如果 \(i\) 为偶数,就把操作一次会赢的 \(lst_{i,j}\) 清空,否则若 \(i\) 为奇数,如果存在符合的 \(lst_{i,j}\),答案就为 \(1\)。
最后,如果在自己在 \(pos\) 位置不做操作就已经赢了,还需要满足 \(lst_{i,j} \leq pos\)。
这些都可以 \(O(n)\) 维护。
代码:(这里的 \(lst_{i,j}\) 进行了状态压缩)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define flush() fwrite(obuf,1,O-obuf,stdout)
#define putchar(x) ((O==obuf+(1<<21))&&(flush(),O=obuf)),*O++=x
char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
register int x=0,f=1;register char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return x*f;
}
inline void write(register int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar((x%10)^48);
}
struct Flush{
~Flush(){flush();}
}_;
#define N 100010
int t,n,a[N*2],ans;
signed main(){
int T;
cin>>t;
T=t;
while(t--){
ans=556676;
cin>>n;
for(int i=1;i<=2*n;i++){
a[i]=0;
}
for(int i=1;i<=n;i++){
char c;
cin>>c;
if(c=='P'){
a[2*i-1]=0;
}
else{
if(c=='V'){
a[2*i-1]=1;
}
else{
a[2*i-1]=2;
}
}
}
for(int i=1;i<=n;i++){
char c;
cin>>c;
if(c=='P'){
a[2*i]=0;
}
else{
if(c=='V'){
a[2*i]=1;
}
else{
a[2*i]=2;
}
}
}
int s[3]={};
for(int i=1;i<=2*n;i++){
s[a[i]]++;
if(s[0]==s[1]&&s[1]==s[2]){
if(i%2==1){
ans=0;
}
break;
}
}
if(ans==0){
cout<<0<<endl;
continue;
}
s[0]=s[1]=s[2]=0;
int pos=2*n;
int lst[9]={};
for(int i=1;i<=2*n;i++){
if(i<=pos){
lst[a[i]*3+0]=lst[a[i]*3+1]=lst[a[i]*3+2]=i;
}
s[a[i]]++;
if(i%2==0){
if(s[0]==s[1]&&s[0]==s[2]){
pos=min(pos,i);
continue;
}
if(s[0]==s[1]-1&&s[1]==s[2]-1){
lst[6]=0;
}
if(s[0]==s[2]-1&&s[2]==s[1]-1){
lst[3]=0;
}
if(s[1]==s[0]-1&&s[0]==s[2]-1){
lst[7]=0;
}
if(s[1]==s[2]-1&&s[2]==s[0]-1){
lst[1]=0;
}
if(s[2]==s[0]-1&&s[0]==s[1]-1){
lst[5]=0;
}
if(s[2]==s[1]-1&&s[1]==s[0]-1){
lst[2]=0;
}
}
else{
if(s[0]==s[1]-1&&s[1]==s[2]-1){
if(lst[6]&&lst[6]<=pos){
ans=1;
break;
}
}
if(s[0]==s[2]-1&&s[2]==s[1]-1){
if(lst[3]&&lst[3]<=pos){
ans=1;
break;
}
}
if(s[1]==s[0]-1&&s[0]==s[2]-1){
if(lst[7]&&lst[7]<=pos){
ans=1;
break;
}
}
if(s[1]==s[2]-1&&s[2]==s[0]-1){
if(lst[1]&&lst[1]<=pos){
ans=1;
break;
}
}
if(s[2]==s[0]-1&&s[0]==s[1]-1){
if(lst[5]&&lst[5]<=pos){
ans=1;
break;
}
}
if(s[2]==s[1]-1&&s[1]==s[0]-1){
if(lst[2]&&lst[2]<=pos){
ans=1;
break;
}
}
}
}
if(ans==1){
cout<<1<<endl;
}
else{
cout<<2<<endl;
}
}
return 0;
}
标签:frac,int,题解,else,lst,Cfz,答案,Rose,define
From: https://www.cnblogs.com/awmmmmmm/p/18493714