Codeforces 1086D Rock-Paper-Scissors Champion
阿新 • • 發佈:2018-12-28
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)); } }