Description

\(N\) 个人排成一排, 每个人都事先决定出剪刀、石头、布。

每次可以任意选两个相邻的人进行决斗。 规则和游戏一样。

但是如果平局, 则掷硬币来决定胜负。 输的人下场。

现要求出有几个人 有获胜的可能(即可以任意决定决斗的顺序 和 掷出的硬币)

Solution

一个很显然的结论: 一个人要想获胜, 两边都要满足其中一个条件, 以左边为例:

左边没有能赢他的人, 或者 左边存在一个他能赢的人即可。

根据这个结论, 我们分别计算出剪刀 、石头、 布的人有多少人能赢。

以计算出剪刀有多少人能赢为例, 先找出最先出布的人和最后出布的人, 这两个人中间的人都可以赢, 记入贡献

然后再剩余出剪刀的人 左边没有人出石头 和 右边没有人出石头的人的个数。

用\(Bit\)和\(Set\) 可以\(O(logN)\)计算。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#define up(a, b) (a = a > b ? a : b)
#define down(a, b) (a = a > b ? b : a)
#define cmax(a, b) (a > b ? a : b)
#define cmin(a, b) (a > b ? b : a)
#define Abs(a) ((a) > 0 ? (a) : -(a))
#define lowbit(x) ((x) & -(x))
#define rd read()
#define db double
#define LL long long
using namespace std;
typedef pair<int, int> P; /*
inline char nc(){
static char buf[1<<14],*p1=buf,*p2=buf;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline LL read(){
char c=nc();LL x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
return x*f;
}
*/ int read() {
int X = 0, p = 1; char c = getchar();
for (; c > '9' || c < '0'; c = getchar())
if (c == '-') p = -1;
for (; c >= '0' && c <= '9'; c = getchar())
X = X * 10 + c - '0';
return X * p;
} const int N = 2e5 + 5; int n, m, sum[4][N];
char s[N];
set<int> S[4]; int ch(char c) {
if (c == 'R')
return 0;
if (c == 'P')
return 1;
if (c == 'S')
return 2;
} void add(int x, int d, int *p) {
for (; x <= n; x += lowbit(x))
p[x] += d;
} int query(int x, int *p) {
if (x < 0) return 0;
int res = 0;
for (; x; x -= lowbit(x))
res += p[x];
return res;
} int work(int x) {
int y = (x + 2) % 3; //x > y
int z = (x + 1) % 3; //z > x
int res = 0;
if (!S[y].size()) {
if (S[z].size())
return 0;
else return n;
}
int l = *(S[y].begin()), r = *(--S[y].end());
if (S[y].size() > 1)
res += query(r, sum[x]) - query(l - 1, sum[x]);
int tmp = S[z].size() ? *(S[z].begin()) : n + 1;
down(tmp, l);
res += query(tmp, sum[x]); tmp = S[z].size() ? *(--S[z].end()) : 0;
up(tmp, r);
res += query(n, sum[x]) - query(tmp - 1, sum[x]);
return res;
} int main()
{
n = rd; m = rd;
scanf("%s", s + 1);
for (int i = 1; i <= n; ++i) {
add(i, 1, sum[ch(s[i])]);
S[ch(s[i])].insert(i);
}
printf("%d\n", work(0) + work(1) + work(2));
for (int i = 1; i <= m; ++i) {
int x = rd; char c = getchar();
for (; !(c == 'R' || c == 'P' || c == 'S');)
c = getchar();
S[ch(s[x])].erase(x); add(x, -1, sum[ch(s[x])]);
s[x] = c;
S[ch(s[x])].insert(x); add(x, 1, sum[ch(s[x])]);
printf("%d\n", work(0) + work(1) + work(2));
}
}

Codeforces 1086D Rock-Paper-Scissors Champion的更多相关文章

  1. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  2. SDUT 3568 Rock Paper Scissors 状压统计

    就是改成把一个字符串改成三进制状压,然后分成前5位,后5位统计, 然后直接统计 f[i][j][k]代表,后5局状压为k的,前5局比和j状态比输了5局的有多少个人 复杂度是O(T*30000*25*m ...

  3. FFT(Rock Paper Scissors Gym - 101667H)

    题目链接:https://vjudge.net/problem/Gym-101667H 题目大意:首先给你两个字符串,R代表石头,P代表布,S代表剪刀,第一个字符串代表第一个人每一次出的类型,第二个字 ...

  4. Gym - 101667H - Rock Paper Scissors FFT 求区间相同个数

    Gym - 101667H:https://vjudge.net/problem/Gym-101667H 参考:https://blog.csdn.net/weixin_37517391/articl ...

  5. Gym101667 H. Rock Paper Scissors

    将第二个字符串改成能赢对方时对方的字符并倒序后,字符串匹配就是卷积的过程. 那么就枚举字符做三次卷积即可. #include <bits/stdc++.h> struct Complex ...

  6. 【题解】CF1426E Rock, Paper, Scissors

    题目戳我 \(\text{Solution:}\) 考虑第二问,赢的局数最小,即输和平的局数最多. 考虑网络流,\(1,2,3\)表示\(Alice\)选择的三种可能性,\(4,5,6\)同理. 它们 ...

  7. 题解 CF1426E - Rock, Paper, Scissors

    一眼题. 第一问很简单吧,就是每个 \(\tt Alice\) 能赢的都尽量让他赢. 第二问很简单吧,就是让 \(\tt Alice\) 输的或平局的尽量多,于是跑个网络最大流.\(1 - 3\) 的 ...

  8. HDOJ(HDU) 2164 Rock, Paper, or Scissors?

    Problem Description Rock, Paper, Scissors is a two player game, where each player simultaneously cho ...

  9. HDU 2164 Rock, Paper, or Scissors?

    http://acm.hdu.edu.cn/showproblem.php?pid=2164 Problem Description Rock, Paper, Scissors is a two pl ...

  10. 1090-Rock, Paper, Scissors

    描述 Rock, Paper, Scissors is a classic hand game for two people. Each participant holds out either a ...

随机推荐

  1. html 文本解码 xpath 获取html标签

    import htmlimport etree selector = etree.HTML(res) url_h2 = selector.xpath("//a[@_stat='video:p ...

  2. vue项目中icon图标的完美引入

    第一步: 进入阿里矢量图标库并登录 地址:https://www.iconfont.cn 第二步: 选择项目需要的图标添加到库 第三步: 选完之后点击右上角的购物车,打开后点击添加到项目,没有就自己建 ...

  3. matlab-逻辑回归二分类(Logistic Regression)

    逻辑回归二分类 今天尝试写了一下逻辑回归分类,把代码分享给大家,至于原理的的话请戳这里 https://blog.csdn.net/laobai1015/article/details/7811321 ...

  4. windows环境下安装rabbitmq及配置可视化管理界面

    1.环境 windows7 64位 rabbitmq3.7.9 erlang10.22.先安装erlang,后安装rabbitmq.下载地址: rabbitmq http://www.rabbitmq ...

  5. Windows终端工具_MobaXterm

    前言 有人喜欢小而美的工具,有人喜欢大集成工具.这里推荐一款增强型的Windows终端工具MobaXterm,它提供所有重要的远程网络工具(SSH,X11,RDP,VNC,FTP,MOSH ..... ...

  6. C++并发编程学习笔记

    // //  main.cpp //  test1 // //  Created by sofard on 2018/12/27. //  Copyright © 2018年 dapshen. All ...

  7. Linux安装Intel Threading Building Blocks(TBB)

    编译安装: wget https://codeload.github.com/01org/tbb/tar.gz/2019_U3 tar zxvf 2019_U3 cd tbb-2019_U3 make ...

  8. ArcGIS按选定线分割面-案例教程

    ArcGIS按选定线分割面-案例教程 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 功能 方法:高级编辑 实例: 分割前后 联系方式:谢老师,135-4855-43 ...

  9. jmeter学习笔记--概述

    jmeter:概述 是什么? jmeter是Apache 公司使用java开发的一款测试工具 为什么? 高效.功能强大 模拟一些高并发或多次循环等特殊场景 怎么用? 1.下载jmeter,解压缩 2. ...

  10. vue provide和inject 父组件和子孙通信

    父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量.不论子组件有多深,只要调用了inject那么就可以注入provider中的数据.而不是局限于只能从当前父组件的prop ...