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; } |
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步