当前位置: 代码迷 >> 综合 >> 前缀和+枚举 Gym100712B Rock-Paper-Scissors
  详细解决方案

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

热度:16   发布时间:2023-12-14 04:11:18.0

题意:一个人是按数据给出的顺序出石头剪刀布,一个人是先出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;
}


  相关解决方案