仅关注测试数据的前两个子任务
子任务1由于图规模小而查询数目大,因此可以拿二维数组来保存员工坐标
子任务2由于图规模大而查询数目小,因此员工坐标用数组来存储
骗到55分
#include <iostream>
#include <string.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 1010, M = 1e5 + 10;
int g[N][N], ng[N][N];
int d[8][2] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
PII employee[N];
int n, m, p, q;
int ananlyse_k(int u, int v)
{
int k = 0;
int by = min(v - 1, m - v), bx = min(u - 1, n - u);
int k2 = min(bx, by); //获取最近的边界
for (int k1 = k2; k1 > 0; k1-- ) { //这一步已经保证了不会出界
for (int i = 0; i < 8; i++ ) {
int dx = d[i][0], dy = d[i][1];
int nx = u + k1 * dx, ny = v + k1 * dy;
if (g[nx][ny]) { //k1时刻,i方向上有员工
k = k1;
}
}
}
//直到边界了也没找到龙
//k的值已经确定
return k;
}
int has_direction(int u, int v, int x, int y)
{
int dx = abs(u - x), dy = abs(v - y);
if (dx == 0 and dy != 0) { //上下方
return dy;
}
else if (dx != 0 and dy == 0) { //左右
return dx;
}
else if (dx != 0 and dy != 0 and dx == dy) { //对角
return dx;
}
else { //不在8个方向上
return -1;
}
}
void print(int grid[N][N])
{
for (int i = 1; i <= n; i++ ) {
for (int j = 1; j <= m; j++ ) {
cout << grid[i][j] << " ";
}
cout << endl;
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m >> p >> q;
if (n <= 1000) {
for (int i = 1; i <= p; i++ ) { //p个员工
int x, y; cin >> x >> y;
g[x][y] = i;
}
for (int i = 0; i < q; i++ ) {
//memcpy(ng, g, sizeof(g)); //全部把状态存下来太慢了,只要存周围8个就行
//print(g);
int u, v, t; cin >> u >> v >> t;
int k = ananlyse_k(u, v);
//cout << k << endl;
if (k > 0) {
int last[8]; //保存旋转前8个方向对应的员工,防止值的覆盖问题
for (int j = 0; j < 8; j++ ) {
int nx = u + k * d[j][0], ny = v + k * d[j][1];
last[j] = g[nx][ny]; //分别记录
g[nx][ny] = 0; //先把这些位置全部清零
//g[nx][ny] = 0;
}
for (int j = 0; j < 8; j++ ) {
//移动员工的操作
int tx = u + k * d[(j + t) % 8][0];
int ty = v + k * d[(j + t) % 8][1];
if (last[j]) { //对应的位置原来是有员工的
g[tx][ty] = last[j]; //把员工放到新位置上去
}
}
//print(ng);
//memcpy(g, ng, sizeof(ng));
}
}
int res = 0;
for (int i = 1; i <= n; i++ ) {
for (int j = 1; j <= m; j++ ) {
if (g[i][j]) {
int cur = g[i][j] * i + j;
res = res ^ cur;
}
}
}
cout << res << endl;
}
else { //子任务2
for (int i = 1; i <= p; i++ ) { //1000个人,1e9的坐标,开一个PII数组记录P个员工的坐标
cin >> employee[i].first >> employee[i].second;
}
while (q-- ) {
int u, v, t; cin >> u >> v >> t;
int bx = min(u - 1, n - u), by = min(v - 1, m - v);
int k2 = min(bx, by);
int k = 0x3f3f3f3f;
for (int i = 1; i <= p; i++ ) {
int x = employee[i].first, y = employee[i].second;
int ck = has_direction(u, v, x, y); //判断是否在8个方向上,并计算距离k
if (ck != -1) {
k = min(k, ck);
}
}
if (k > k2) k = 0;
for (int i = 1; i <= p; i++ ) { //旋转操作
int x = employee[i].first, y = employee[i].second;
int dir = -1;
for (int j = 0; j < 8; j++ ) { //找出方向
int nx = u + k * d[j][0], ny = v + k * d[j][1];
if (nx == x and ny == y) {
dir = j;
break;
}
}
if (dir != -1) {
int tx = u + k * d[(dir + t) % 8][0], ty = v + k * d[(dir + t) % 8][1];
employee[i].first = tx, employee[i].second = ty;
}
}
}
LL res = 0;
for (int i = 1; i <= p; i++ ) {
res = (LL)res ^ ((LL)i * (LL)employee[i].first + employee[i].second);
}
cout << res << endl;
}
return 0;
}