CodeForces - 1087F:Rock-Paper-Scissors Champion(set&数状数组)

n

players are going to play a rock-paper-scissors tournament. As you probably know, in a one-on-one match of rock-paper-scissors, two players choose their shapes independently. The outcome is then determined depending on the chosen shapes: "paper" beats "rock", "rock" beats "scissors", "scissors" beat "paper", and two equal shapes result in a draw.

At the start of the tournament all players will stand in a row, with their numbers increasing from 1

for the leftmost player, to n

for the rightmost player. Each player has a pre-chosen shape that they will use in every game throughout the tournament. Here's how the tournament is conducted:

  • If there is only one player left, he is declared the champion.
  • Otherwise, two adjacent players in the row are chosen arbitrarily, and they play the next match. The losing player is eliminated from the tournament and leaves his place in the row (with his former neighbours becoming adjacent). If the game is a draw, the losing player is determined by a coin toss.

The organizers are informed about all players' favoured shapes. They wish to find out the total number of players who have a chance of becoming the tournament champion (that is, there is a suitable way to choose the order of the games and manipulate the coin tosses). However, some players are still optimizing their strategy, and can inform the organizers about their new shapes. Can you find the number of possible champions after each such request?

Input

The first line contains two integers n

and q — the number of players and requests respectively (1n2105, 0q2105

).

The second line contains a string of n

characters. The i-th of these characters is "R", "P", or "S" if the player i

was going to play "rock", "paper", or "scissors" before all requests respectively.

The following q

lines describe the requests. The j-th of these lines contain an integer pj and a character cj meaning that the player pj is going to use the shape described by the character cj from this moment (1pjn

).

Output

Print q+1

integers r0,,rq, where rk is the number of possible champions after processing k

requests.

Example
Input
3 5
RPS
1 S
2 R
3 P
1 P
2 P
Output
2
2
1
2
2
3

题意:给定一排的人,每一轮可以人为决定两个人划拳,如果是平局,人为决定其中一个赢。问每次修改一个人的出拳方式,又多少个人可以win。

思路:一个人win的充要条件是左右同时满足:或没有可以打败他的,或者至少一个他可以打败的。

区间人数,我们可以用BIT维护。分三种情况累加即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
char c[maxn]; set<int>s[3]; int sum[3][maxn],N;
int id(char p){
    if(p=='R') return 0; if(p=='S') return 1; return 2;
}
void add(int opt,int x,int val)
{
    for(;x<=N;x+=(-x)&x) sum[opt][x]+=val;
}
int query(int opt,int x){
    int res=0; for(;x;x-=(-x)&x) res+=sum[opt][x]; return res;
}
int cal(int p)
{
    int lat=(p+2)%3,pre=(p+1)%3;
    if(s[lat].empty()) return query(p,N); //set为空时不能用rbegin
    if(s[pre].empty()) return 0;
    return query(p,N)-query(p,max(*s[pre].rbegin(),*s[lat].rbegin()))+//左边有可以被p打败的,右边无可以打败p的
           query(p,min(*s[pre].begin(),*s[lat].begin()))+//右边有可以被p打败的,左边无可以打败p的
           query(p,*s[pre].rbegin())-query(p,*s[pre].begin());//左右都有可以被p打败的
}
int main()
{
    int M,pos,ans,p; char cc[3];
    scanf("%d%d%s",&N,&M,c+1);
    rep(i,1,N){
        p=id(c[i]);
        s[p].insert(i); add(p,i,1);
    }
    ans=cal(0)+cal(1)+cal(2);
    printf("%d\n",ans);
    rep(i,1,M){
        scanf("%d%s",&pos,cc+1);
        if(c[pos]==cc[1]){ printf("%d\n",ans);continue;}
        p=id(c[pos]); s[p].erase(pos); add(p,pos,-1); //
        c[pos]=cc[1]; p=id(c[pos]); s[p].insert(pos); add(p,pos,1); //
        ans=cal(0)+cal(1)+cal(2);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/10176321.html