• #2488. 象棋游戏(topovi)


    题目描述
    Mirko是一个象棋爱好者,他在一个 $N imes N$ 的棋盘上放置 $K$ 个车,游戏规则如下:

    - 每个车有一个权值。

    - 每个车可以看到它所在的行和列上的所有其他格子(不包括本身)。

    - 一个格子被攻击当且仅当它所能看到的所有车的权值异或值大于 $0$ 。

    现在,Mirko要对棋盘上的一些车进行 $P$ 次移动,每个车可以移动到棋盘上的任意一个空格子(不只是行和列上的移动),请你帮忙计算对于每次移动后棋盘上有多少个格子被攻击

    数据范围
    对于100%数据,$1 le N le 1000000000, 1 le K le 100000, 1 le P le 100000, 1 le R,C le N, 1 le X le 1000000000$

    题解
    看对题比较重要

    可以转化一下题意:找出有多少数对 $(r,c)$ ,其中第 $r$ 行的异或和和第 $c$ 列的异或和不等

    考虑到求相等更方便,最后用 $n imes n-cnt$ 即可

    于是用 $map_{r/c,v}$ 表示的是异或和是 $v$ 的行数/列数,注意异或和等于 $0$ 的要加上未出现过的行数/列数

    修改的时候考虑到不在原来或新的位置所在的行或列的格子的贡献是不受影响的,于是只要重新计算下原来或新的位置的行或列上的格子贡献即可

    效率: $O((k+p)logn)$

    代码

    #include <bits/stdc++.h>
    #define M make_pair
    #define LL long long
    using namespace std;
    const int N=2e5+5;
    int n,k,p,vr[N],vc[N],dr,dc;
    map<int,int>R,C,Vr,Vc;
    map<pair<int,int>,int>g;LL ans;
    int main(){
        scanf("%d%d%d",&n,&k,&p);
        for (int r,c,x,kr,kc,i=1;i<=k;i++){
            scanf("%d%d%d",&r,&c,&x);g[M(r,c)]=x;
            kr=R[r];if (!kr) kr=R[r]=++dr;vr[kr]^=x;
            kc=C[c];if (!kc) kc=C[c]=++dc;vc[kc]^=x;
        }
        Vc[0]+=n-dc;
        for (int i=1;i<=dr;i++) Vr[vr[i]]++;
        for (int i=1;i<=dc;i++) Vc[vc[i]]++;
        for (int i=1;i<=dr;i++) ans+=Vc[vr[i]];
        ans+=1ll*(n-dr)*Vc[0];Vr[0]+=n-dr;
        for (int v,r1,c1,r2,c2;p--;){
            scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
            if (!R[r2]) R[r2]=++dr;
            if (!C[c2]) C[c2]=++dc;
            v=g[M(r1,c1)];g[M(r2,c2)]=v;
            r1=R[r1];r2=R[r2];c1=C[c1];c2=C[c2];
            ans-=Vr[vc[c1]]+(c1!=c2)*Vr[vc[c2]];
            ans-=Vc[vr[r1]]+(r1!=r2)*Vc[vr[r2]];
            if (vr[r1]==vc[c1]) ans++;
            if (vr[r2]==vc[c2]) ans++;
            if (r1!=r2 && c1!=c2){
                if (vr[r1]==vc[c2]) ans++;
                if (vr[r2]==vc[c1]) ans++;
            }
            Vr[vr[r1]]--;if (r1!=r2) Vr[vr[r2]]--;
            Vc[vc[c1]]--;if (c1!=c2) Vc[vc[c2]]--;
            vr[r1]^=v;vr[r2]^=v;vc[c1]^=v;vc[c2]^=v;
            Vr[vr[r1]]++;if (r1!=r2) Vr[vr[r2]]++;
            Vc[vc[c1]]++;if (c1!=c2) Vc[vc[c2]]++;
            ans+=Vr[vc[c1]]+(c1!=c2)*Vr[vc[c2]];
            ans+=Vc[vr[r1]]+(r1!=r2)*Vc[vr[r2]];
            if (vr[r1]==vc[c1]) ans--;
            if (vr[r2]==vc[c2]) ans--;
            if (r1!=r2 && c1!=c2){
                if (vr[r1]==vc[c2]) ans--;
                if (vr[r2]==vc[c1]) ans--;
            }
            printf("%lld
    ",1ll*n*n-ans);
        }
        return 0;
    }
  • 相关阅读:
    bugku crypto 告诉你一个秘密(ISCCCTF)
    递归法求组合数C(m,n)
    bugku 逆向 take the maze
    P1118 [USACO06FEB]数字三角形`Backward Digit Su`… (dfs)
    递归 dfs 记忆化搜索 动态规划
    c++ 取整:四舍五入 向上取整 向下取整
    2019 计蒜之道 初赛 第一场 商汤的AI伴游小精灵
    华南理工大学“三七互娱杯” D HRY and array
    华南理工大学 “三七互娱杯” G HRY and tree
    2019年湘潭大学程序设计竞赛(重现赛)
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11317408.html
Copyright © 2020-2023  润新知