标签:std get tchar printf str time sig 数据 题解
【题目描述】
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$ 维护每行每列的异或和,并维护行与列每种异或和的个数即可。
【代码】
#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; }
标签:std get tchar printf str time sig 数据 题解
原文地址:https://www.cnblogs.com/RenSheYu/p/11317027.html