题意很好懂,就是一个长度为n的序列,s[i] 只可能是r,g,b,要你要满足就 j - i != k - j,并且s[i],s[j],s[k]两两不相同,并且i < j < k,的个数有多少个。
思路:
暴力O(n^3)模拟一遍铁超时,j - i != k - j 一开始一直在观察这个式子看能不能优化一下,事实上可以不管这个式子就一个区间[i,k]={B,R},那么我们在[i + 1,k - 1]这个区间找有多少个G就行了,需要考虑一下中点是否需要减掉,然后把所有的情况枚举出来就行了。这里用前缀和维护sum [ i ] [ 1 - 3 ]:表示从1到i有多少个R,B,G。
感觉写的有点点复杂了。。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long int ll;
ll sum[maxn][4];
void solved(){
ll n;cin>>n;
char s[5000];scanf("%s",s + 1);
ll r = 0, b = 0,g = 0;
for(int i = 1; i <= n; i++){
if(s[i] == 'R'){
r++;
sum[i][1] = sum[i - 1][1] + 1;
sum[i][2] = sum[i - 1][2];
sum[i][3] = sum[i - 1][3];
}else if(s[i] == 'G'){
g++;
sum[i][1] = sum[i - 1][1];
sum[i][2] = sum[i - 1][2] + 1;
sum[i][3] = sum[i - 1][3];
}else if(s[i] == 'B'){
b++;
sum[i][1] = sum[i - 1][1];
sum[i][2] = sum[i - 1][2];
sum[i][3] = sum[i - 1][3] + 1;
}
}
//cout<<"r :"<<r<<" G:"<<g<<" B:"<<b<<endl;
//cout<<"R: "<<sum[n][1]<<" G:"<<sum[n][2]<<" B:"<<sum[n][3]<<endl;
ll ans = 0;
for(int i = 1; i <= n; i++)
for(int k = i + 1; k <= n; k++){
if(s[i] == 'R' && s[k] == 'B' ){
if((k - i + 1) & 1 && s[(i + k) /2] == 'G')ans --;
ans += sum[k - 1][2] - sum[i][2];
}
if(s[i] == 'B' && s[k] == 'R'){
if((k - i + 1) & 1 && s[(i + k) /2] == 'G')ans --;
ans += sum[k - 1][2] - sum[i][2];
}
if(s[i] == 'G' && s[k] == 'B'){
if((k - i + 1) & 1 && s[(i + k) /2] == 'R')ans --;
ans += sum[k - 1][1] - sum[i][1];
}
if(s[i] == 'B' && s[k] == 'G'){
if((k - i + 1) & 1 && s[(i + k) /2] == 'R')ans --;
ans += sum[k - 1][1] - sum[i][1];
}
if(s[i] == 'R' && s[k] == 'G'){
if((k - i + 1) & 1 && s[(i + k) /2] == 'B')ans --;
ans += sum[k - 1][3] - sum[i][3];
}
if(s[i] == 'G' && s[k] == 'R'){
if((k - i + 1) & 1 && s[(i + k) /2] == 'B')ans --;
ans += sum[k - 1][3] - sum[i][3];
}
}
cout<<ans<<endl;
}
int main(){
solved();
return 0;
}