题解:P12443 [NERC2023] LOL Lovers
思路
作为一道签退题再加上其长达 3s 的时间限制,那么这道题很明显是一道暴力(事实证明这道题你再怎么暴力都不会超时)。
最暴力的方法是枚举每一个字符为分割点,遍历前面的字符串和后方的字符串,统计 \(O\) 和 \(L\) 的个数就行了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],b[N];
string s;
int main(){
int n;
cin>>n>>s;
int cnt1,cnt2,cnt3,cnt4;
for(int i=1;i<n;i++){
cnt1=cnt2=cnt3=cnt4=0;
for(int j=0;j<=i-1;j++){
if(s[j]=='L') cnt1++;
if(s[j]=='O') cnt2++;
}
for(int j=i;j<n;j++){
if(s[j]=='L') cnt3++;
if(s[j]=='O') cnt4++;
}
if(cnt1!=cnt3&&cnt2!=cnt4){
cout<<i;
return 0;
}
}
cout<<"-1";
}
很明显地通过了。
关于暴力的优化
这道题的统计个数用前缀和,统计个数时就可以以 \(O(1)\) 的时间复杂度来查询。将 \(O(n^2)\) 的时间复杂度将为 \(O(n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],b[N];
string s;
int main(){
int n;
cin>>n>>s;
s=' '+s;
for(int i=1;i<=n;i++){
a[i]=a[i-1];
b[i]=b[i-1];
if(s[i]=='O') a[i]++;
if(s[i]=='L') b[i]++;
}
for(int i=1;i<n;i++){
// cout<<a[i]<<" ";
if(a[i]!=a[n]-a[i]&&b[i]!=b[n]-b[i]){
cout<<i<<"\n";
return 0;
}
}
cout<<"-1";
}