Processing math: 0%

DTOJ #2488. 象棋游戏(topovi)

【题目描述】

Mirko是一个象棋爱好者,他在一个 N \times N 的棋盘上放置 K 个车,游戏规则如下:

- 每个车有一个权值。

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

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

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

【输入格式】

第一行包含三个整数 N,K,P

接下来 K 行,每行包含三个整数 R,C,X,表示在 (R,C) 位置上的车的权值为 X

接下来 P 行,每行包含四个整数 R1,C1,R2,C2,表示将 (R1,C1) 位置上的车移动到(R2,C2)

数据保证不会出现两个车在同一格子。

【输出格式】

输出包含 P 行,第 i 行表示经过 i 次移动之后,棋盘上有多少个格子被攻击。

【样例】

样例输入
3 3 4
1 1 1
2 2 2
2 3 3
2 3 3 3
3 3 3 1
1 1 1 2
3 1 3 2

样例输出
6
7
7
9

【数据范围与提示】

对于25%数据,1 \le N,K \le 100

对于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

【题解】

难得有道良心水题。。。考查 STL 的基础应用。

显然行与列异或和相同的位置就不会被攻击,用 map 维护每行每列的异或和,并维护行与列每种异或和的个数即可。

【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<bits/stdc++.h>
inline int read ( void )
{
    int x=0;char ch;bool f=true;
    while ( !isdigit(ch=getchar()) ) if ( ch=='-' ) f=false;
    for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
    return f ? x : -x ;
}
int n,k,p,val[100010];
long long ans;
std::map<std::pair<int,int>,int> id;
std::map<int,int> cntx,cnty,sumx,sumy;
inline void Insert ( int x,int y,int val )
{
    cntx[sumx[x]]--;cnty[sumy[y]]--;
    ans+=cnty[sumx[x]]+cntx[sumy[y]];
    sumx[x]^=val;sumy[y]^=val;
    ans-=cnty[sumx[x]]+cntx[sumy[y]];
    cntx[sumx[x]]++;cnty[sumy[y]]++;
}
signed main()
{
    n=read();k=read();p=read();cntx[0]=cnty[0]=n;
    for ( int i=1;i<=k;i++ ) { int r=read(),c=read();val[i]=read();id[std::make_pair(r,c)]=i;Insert(r,c,val[i]); }
    while ( p-- )
    {
        int r1=read(),c1=read(),r2=read(),c2=read(),i=id[std::make_pair(r1,c1)];id[std::make_pair(r1,c1)]=0;
        Insert(r1,c1,val[i]);Insert(r2,c2,val[i]);id[std::make_pair(r2,c2)]=i;printf("%lld\n",ans);
    }
    return 0;
}

  

posted @   DTOI_RSY  阅读(206)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示