不点两面 (安全牌)

我愿称这思路为 先斩后奏【拿到牌直接先分出安全牌,先不管(op)是拿牌 还是弃牌】(有python和c++的代码 思路一样 可以看逐行注解)

c++代码

#include<bits/stdc++.h>
const int N=1e7+10;
int a[N];//判断安全牌是否使用过
using namespace std;
int safe[3];//暂存安全牌
int main(){
    memset(a,0, sizeof(a));//所有安全牌数值置0
    int m,q;
    int cnt=0;//判断有几张安全牌
    scanf("%d%d",&m,&q);
    for(int i=1;i<=q;i++){
        int op;// 1对方拿牌 2对方弃牌
        int sum;//对方拿到的牌
        scanf("%d%d",&op,&sum);
        int l=(sum-3);//对方拿到的牌 你对应的安全牌(x-3)
        int r=(sum+3);//对方拿到的牌 你对应的安全牌(x+3)
        safe[1]=l;
        safe[2]=r;
        for(int j=1;j<=2;j++){
            if(safe[j]<1 || safe[j]>m)continue;//越界抛出
            //对方拿牌
            if(op==1){
                if(a[safe[j]]==0){//表示这个安全牌没使用
                    cnt++;//安全牌数量增加
                }
                 //对应安全牌数量增加
                a[safe[j]]++;
            }
            //对方弃牌
            else{
                if(a[safe[j]]==1){
                    //若对方手上只有一张并且要扔 
                    // 那你对应的安全牌也可以扔了
                    cnt--;//安全牌数量减少
                }
                //对应安全牌数量减少
                a[safe[j]]--;
            }
            }
         printf("%d\n",cnt);
    }
    
}


Python3 代码

m,q = map(int,input().split())
book = [0 for i in range(m+10)]
cnt = 0
for i in range(q):
    op,num = map(int,input().split())
    #拿到数直接判安全牌
    for j in [num-3,num+3]:
        if j > m or j < 1:
            continue
            #加入
        if op == 1:
            #判断该数是否使用过
            if book[j] == 0:
                cnt += 1
            book[j] += 1
            #抛出
        else:
            if book[j] == 1:
                cnt -= 1
            book[j] -= 1
    print(cnt)


如有错,请大佬在评论指出,谢谢