Bootstrap

前缀和+枚举 Gym100712B Rock-Paper-Scissors

题意:一个人是按数据给出的顺序出石头剪刀布,一个人是先出X个石头,Y个布,Z个剪刀

用前缀和来维护R,P,S数组,R[i]表示前i个中有多少个R


cnt1用来统计能打赢的,cnt2统计平手的次数

因为一个区间分成了3段,那么有两个节点,枚举中间两个节点即可

然后看那3段中分别有多少个能打赢的,和能打成平手的,统计一下满足条件的次数,就是答案了


#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<functional>
#include<algorithm>

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MX = 200000 + 5;
const int INF = 0x3f3f3f3f;

char line[MX];
int R[MX], P[MX], S[MX];

int main() {
    //freopen("input.txt","r",stdin);

    int T, L;
    scanf("%d", &T);
    while(T--) {
        memset(R, 0, sizeof(R));
        memset(P, 0, sizeof(P));
        memset(S, 0, sizeof(S));

        scanf("%d%s", &L, line + 1);

        for(int i = 1; i <= L; i++) {
            R[i] = R[i - 1];
            P[i] = P[i - 1];
            S[i] = S[i - 1];
            if(line[i] == 'R') R[i]++;
            if(line[i] == 'P') P[i]++;
            if(line[i] == 'S') S[i]++;
        }

        int ans = 0;
        for(int i = 0; i <= L; i++) {
            for(int j = i; j <= L; j++) {
                int cnt1 = S[i], cnt2 = R[i];
                if(j >= i) cnt1 += R[j] - R[i], cnt2 += P[j] - P[i];
                if(L >= j) cnt1 += P[L] - P[j], cnt2 += S[L] - S[j];

                if(cnt1 > L - cnt1 - cnt2) {
                    ans++;
                }
            }
        }

        printf("%d\n", ans);
    }
    return 0;
}


;