題意很好懂,就是一個長度爲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;
}